From 9c18d1c230e68c3fcee2fa8c3c1f92c08637a784 Mon Sep 17 00:00:00 2001 From: Hieu Hoang Date: Sat, 3 Sep 2016 02:02:03 +0100 Subject: [PATCH] add cpu --- CMakeLists.txt | 2 +- amunmt/.cproject | 7 +- amunmt/.project | 5 + src/CMakeLists.txt | 4 + src/cpu/blaze/Blaze.h | 60 + src/cpu/blaze/Math.h | 84 + src/cpu/blaze/Tutorial.h | 10694 ++++++++++++++ src/cpu/blaze/Util.h | 90 + src/cpu/blaze/config/Assertion.h | 65 + src/cpu/blaze/config/BLAS.h | 92 + src/cpu/blaze/config/CacheSize.h | 51 + src/cpu/blaze/config/Config.h | 53 + src/cpu/blaze/config/Debugging.h | 55 + src/cpu/blaze/config/Inline.h | 75 + src/cpu/blaze/config/Logging.h | 93 + src/cpu/blaze/config/MPI.h | 51 + src/cpu/blaze/config/Optimizations.h | 87 + src/cpu/blaze/config/Precision.h | 50 + src/cpu/blaze/config/Random.h | 51 + src/cpu/blaze/config/Restrict.h | 47 + src/cpu/blaze/config/SMP.h | 54 + src/cpu/blaze/config/StorageOrder.h | 59 + src/cpu/blaze/config/Thresholds.h | 1308 ++ src/cpu/blaze/config/TransposeFlag.h | 59 + src/cpu/blaze/config/Vectorization.h | 54 + src/cpu/blaze/math/Accuracy.h | 906 ++ src/cpu/blaze/math/Aliases.h | 428 + src/cpu/blaze/math/AlignmentFlag.h | 90 + src/cpu/blaze/math/BLAS.h | 50 + src/cpu/blaze/math/Column.h | 315 + src/cpu/blaze/math/CompressedMatrix.h | 465 + src/cpu/blaze/math/CompressedVector.h | 330 + src/cpu/blaze/math/Constants.h | 208 + src/cpu/blaze/math/Constraints.h | 132 + src/cpu/blaze/math/CustomMatrix.h | 356 + src/cpu/blaze/math/CustomVector.h | 140 + src/cpu/blaze/math/DenseMatrix.h | 103 + src/cpu/blaze/math/DenseVector.h | 69 + src/cpu/blaze/math/DiagonalMatrix.h | 685 + src/cpu/blaze/math/DynamicMatrix.h | 395 + src/cpu/blaze/math/DynamicVector.h | 186 + src/cpu/blaze/math/Epsilon.h | 906 ++ src/cpu/blaze/math/Exception.h | 150 + src/cpu/blaze/math/Forward.h | 49 + src/cpu/blaze/math/Functions.h | 462 + src/cpu/blaze/math/Functors.h | 77 + src/cpu/blaze/math/HermitianMatrix.h | 687 + src/cpu/blaze/math/HybridMatrix.h | 412 + src/cpu/blaze/math/HybridVector.h | 188 + src/cpu/blaze/math/Infinity.h | 1103 ++ src/cpu/blaze/math/InitializerList.h | 91 + src/cpu/blaze/math/InversionFlag.h | 88 + src/cpu/blaze/math/LAPACK.h | 84 + src/cpu/blaze/math/LowerMatrix.h | 810 ++ src/cpu/blaze/math/Math.h | 49 + src/cpu/blaze/math/Matrix.h | 94 + src/cpu/blaze/math/PaddingFlag.h | 91 + src/cpu/blaze/math/Row.h | 315 + src/cpu/blaze/math/SIMD.h | 48 + src/cpu/blaze/math/SMP.h | 50 + src/cpu/blaze/math/Serialization.h | 47 + src/cpu/blaze/math/Shims.h | 84 + src/cpu/blaze/math/SparseMatrix.h | 81 + src/cpu/blaze/math/SparseVector.h | 66 + src/cpu/blaze/math/StaticMatrix.h | 382 + src/cpu/blaze/math/StaticVector.h | 187 + src/cpu/blaze/math/StorageOrder.h | 104 + src/cpu/blaze/math/StrictlyLowerMatrix.h | 673 + src/cpu/blaze/math/StrictlyUpperMatrix.h | 673 + src/cpu/blaze/math/Submatrix.h | 342 + src/cpu/blaze/math/Subvector.h | 315 + src/cpu/blaze/math/SymmetricMatrix.h | 686 + src/cpu/blaze/math/Traits.h | 235 + src/cpu/blaze/math/TransposeFlag.h | 78 + src/cpu/blaze/math/TypeTraits.h | 168 + src/cpu/blaze/math/UniLowerMatrix.h | 786 ++ src/cpu/blaze/math/UniUpperMatrix.h | 785 ++ src/cpu/blaze/math/UpperMatrix.h | 810 ++ src/cpu/blaze/math/Vector.h | 378 + src/cpu/blaze/math/Views.h | 48 + src/cpu/blaze/math/adaptors/Adaptors.h | 51 + src/cpu/blaze/math/adaptors/DiagonalMatrix.h | 2208 +++ src/cpu/blaze/math/adaptors/Forward.h | 59 + src/cpu/blaze/math/adaptors/HermitianMatrix.h | 2130 +++ src/cpu/blaze/math/adaptors/LowerMatrix.h | 2174 +++ .../blaze/math/adaptors/StrictlyLowerMatrix.h | 1731 +++ .../blaze/math/adaptors/StrictlyUpperMatrix.h | 1840 +++ src/cpu/blaze/math/adaptors/SymmetricMatrix.h | 1879 +++ src/cpu/blaze/math/adaptors/UniLowerMatrix.h | 2562 ++++ src/cpu/blaze/math/adaptors/UniUpperMatrix.h | 2671 ++++ src/cpu/blaze/math/adaptors/UpperMatrix.h | 2279 +++ .../adaptors/diagonalmatrix/BaseTemplate.h | 562 + .../math/adaptors/diagonalmatrix/Dense.h | 2650 ++++ .../adaptors/diagonalmatrix/DiagonalProxy.h | 665 + .../math/adaptors/diagonalmatrix/Sparse.h | 2022 +++ .../adaptors/hermitianmatrix/BaseTemplate.h | 617 + .../math/adaptors/hermitianmatrix/Dense.h | 3018 ++++ .../hermitianmatrix/HermitianElement.h | 434 + .../adaptors/hermitianmatrix/HermitianProxy.h | 851 ++ .../adaptors/hermitianmatrix/HermitianValue.h | 811 ++ .../math/adaptors/hermitianmatrix/Sparse.h | 2404 ++++ .../math/adaptors/lowermatrix/BaseTemplate.h | 555 + .../blaze/math/adaptors/lowermatrix/Dense.h | 2740 ++++ .../math/adaptors/lowermatrix/LowerProxy.h | 665 + .../blaze/math/adaptors/lowermatrix/Sparse.h | 2072 +++ .../strictlylowermatrix/BaseTemplate.h | 560 + .../math/adaptors/strictlylowermatrix/Dense.h | 2757 ++++ .../adaptors/strictlylowermatrix/Sparse.h | 2112 +++ .../strictlylowermatrix/StrictlyLowerProxy.h | 670 + .../strictlyuppermatrix/BaseTemplate.h | 560 + .../math/adaptors/strictlyuppermatrix/Dense.h | 2757 ++++ .../adaptors/strictlyuppermatrix/Sparse.h | 2111 +++ .../strictlyuppermatrix/StrictlyUpperProxy.h | 669 + .../adaptors/symmetricmatrix/BaseTemplate.h | 614 + .../symmetricmatrix/DenseNonNumeric.h | 2650 ++++ .../adaptors/symmetricmatrix/DenseNumeric.h | 2970 ++++ .../symmetricmatrix/NonNumericProxy.h | 650 + .../adaptors/symmetricmatrix/NumericProxy.h | 780 ++ .../adaptors/symmetricmatrix/SharedValue.h | 314 + .../symmetricmatrix/SparseNonNumeric.h | 2720 ++++ .../adaptors/symmetricmatrix/SparseNumeric.h | 2345 ++++ .../symmetricmatrix/SymmetricElement.h | 403 + .../adaptors/symmetricmatrix/SymmetricValue.h | 767 ++ .../adaptors/unilowermatrix/BaseTemplate.h | 579 + .../math/adaptors/unilowermatrix/Dense.h | 2697 ++++ .../math/adaptors/unilowermatrix/Sparse.h | 2211 +++ .../adaptors/unilowermatrix/UniLowerElement.h | 367 + .../adaptors/unilowermatrix/UniLowerProxy.h | 809 ++ .../adaptors/unilowermatrix/UniLowerValue.h | 753 + .../adaptors/uniuppermatrix/BaseTemplate.h | 578 + .../math/adaptors/uniuppermatrix/Dense.h | 2696 ++++ .../math/adaptors/uniuppermatrix/Sparse.h | 2211 +++ .../adaptors/uniuppermatrix/UniUpperElement.h | 367 + .../adaptors/uniuppermatrix/UniUpperProxy.h | 809 ++ .../adaptors/uniuppermatrix/UniUpperValue.h | 753 + .../math/adaptors/uppermatrix/BaseTemplate.h | 555 + .../blaze/math/adaptors/uppermatrix/Dense.h | 2739 ++++ .../blaze/math/adaptors/uppermatrix/Sparse.h | 2071 +++ .../math/adaptors/uppermatrix/UpperProxy.h | 665 + src/cpu/blaze/math/blas/BLAS.h | 51 + src/cpu/blaze/math/blas/dot.h | 227 + src/cpu/blaze/math/blas/gemm.h | 298 + src/cpu/blaze/math/blas/gemv.h | 337 + src/cpu/blaze/math/blas/trmm.h | 289 + src/cpu/blaze/math/blas/trmv.h | 312 + src/cpu/blaze/math/blas/trsm.h | 358 + src/cpu/blaze/math/constraints/Adaptor.h | 87 + src/cpu/blaze/math/constraints/AddExpr.h | 87 + src/cpu/blaze/math/constraints/Aligned.h | 87 + .../blaze/math/constraints/BLASCompatible.h | 87 + src/cpu/blaze/math/constraints/Column.h | 87 + .../math/constraints/ColumnMajorMatrix.h | 87 + src/cpu/blaze/math/constraints/ColumnVector.h | 87 + src/cpu/blaze/math/constraints/Columns.h | 101 + src/cpu/blaze/math/constraints/Computation.h | 87 + .../blaze/math/constraints/ConstDataAccess.h | 87 + src/cpu/blaze/math/constraints/Constraints.h | 51 + src/cpu/blaze/math/constraints/CrossExpr.h | 87 + src/cpu/blaze/math/constraints/Custom.h | 87 + src/cpu/blaze/math/constraints/DenseMatrix.h | 87 + src/cpu/blaze/math/constraints/DenseVector.h | 87 + src/cpu/blaze/math/constraints/Diagonal.h | 85 + src/cpu/blaze/math/constraints/DivExpr.h | 87 + src/cpu/blaze/math/constraints/EvalExpr.h | 87 + src/cpu/blaze/math/constraints/Expression.h | 87 + src/cpu/blaze/math/constraints/ForEachExpr.h | 87 + src/cpu/blaze/math/constraints/General.h | 85 + src/cpu/blaze/math/constraints/Hermitian.h | 85 + src/cpu/blaze/math/constraints/Identity.h | 85 + src/cpu/blaze/math/constraints/Invertible.h | 89 + src/cpu/blaze/math/constraints/Lower.h | 87 + src/cpu/blaze/math/constraints/MatEvalExpr.h | 87 + .../blaze/math/constraints/MatForEachExpr.h | 87 + src/cpu/blaze/math/constraints/MatInvExpr.h | 87 + .../blaze/math/constraints/MatMatAddExpr.h | 151 + .../blaze/math/constraints/MatMatMultExpr.h | 145 + .../blaze/math/constraints/MatMatSubExpr.h | 151 + .../blaze/math/constraints/MatScalarDivExpr.h | 87 + .../math/constraints/MatScalarMultExpr.h | 87 + .../blaze/math/constraints/MatSerialExpr.h | 87 + src/cpu/blaze/math/constraints/MatTransExpr.h | 87 + .../blaze/math/constraints/MatVecMultExpr.h | 146 + src/cpu/blaze/math/constraints/Matrix.h | 87 + src/cpu/blaze/math/constraints/MultExpr.h | 87 + .../math/constraints/MutableDataAccess.h | 87 + .../blaze/math/constraints/NumericMatrix.h | 85 + .../blaze/math/constraints/NumericVector.h | 85 + src/cpu/blaze/math/constraints/OpposedView.h | 87 + src/cpu/blaze/math/constraints/Padded.h | 87 + src/cpu/blaze/math/constraints/Proxy.h | 87 + .../math/constraints/RequiresEvaluation.h | 87 + src/cpu/blaze/math/constraints/Resizable.h | 87 + src/cpu/blaze/math/constraints/Restricted.h | 87 + src/cpu/blaze/math/constraints/Row.h | 87 + .../blaze/math/constraints/RowMajorMatrix.h | 87 + src/cpu/blaze/math/constraints/RowVector.h | 87 + src/cpu/blaze/math/constraints/Rows.h | 101 + src/cpu/blaze/math/constraints/SIMDEnabled.h | 87 + src/cpu/blaze/math/constraints/SIMDPack.h | 85 + .../blaze/math/constraints/SMPAssignable.h | 87 + src/cpu/blaze/math/constraints/SerialExpr.h | 87 + src/cpu/blaze/math/constraints/Size.h | 101 + .../blaze/math/constraints/SparseElement.h | 87 + src/cpu/blaze/math/constraints/SparseMatrix.h | 87 + src/cpu/blaze/math/constraints/SparseVector.h | 87 + src/cpu/blaze/math/constraints/Square.h | 85 + src/cpu/blaze/math/constraints/StorageOrder.h | 114 + .../blaze/math/constraints/StrictlyLower.h | 87 + .../math/constraints/StrictlyTriangular.h | 87 + .../blaze/math/constraints/StrictlyUpper.h | 87 + src/cpu/blaze/math/constraints/SubExpr.h | 87 + src/cpu/blaze/math/constraints/Submatrix.h | 87 + src/cpu/blaze/math/constraints/Subvector.h | 87 + src/cpu/blaze/math/constraints/Symmetric.h | 85 + .../blaze/math/constraints/TVecMatMultExpr.h | 146 + src/cpu/blaze/math/constraints/TransExpr.h | 87 + .../blaze/math/constraints/TransposeFlag.h | 114 + src/cpu/blaze/math/constraints/Triangular.h | 87 + src/cpu/blaze/math/constraints/UniLower.h | 87 + .../blaze/math/constraints/UniTriangular.h | 87 + src/cpu/blaze/math/constraints/UniUpper.h | 87 + src/cpu/blaze/math/constraints/Upper.h | 87 + src/cpu/blaze/math/constraints/VecEvalExpr.h | 87 + .../blaze/math/constraints/VecForEachExpr.h | 87 + .../blaze/math/constraints/VecScalarDivExpr.h | 87 + .../math/constraints/VecScalarMultExpr.h | 87 + .../blaze/math/constraints/VecSerialExpr.h | 87 + .../blaze/math/constraints/VecTVecMultExpr.h | 135 + src/cpu/blaze/math/constraints/VecTransExpr.h | 87 + .../blaze/math/constraints/VecVecAddExpr.h | 149 + .../blaze/math/constraints/VecVecDivExpr.h | 149 + .../blaze/math/constraints/VecVecMultExpr.h | 149 + .../blaze/math/constraints/VecVecSubExpr.h | 149 + src/cpu/blaze/math/constraints/Vector.h | 87 + src/cpu/blaze/math/constraints/View.h | 87 + src/cpu/blaze/math/dense/CustomMatrix.h | 6636 +++++++++ src/cpu/blaze/math/dense/CustomVector.h | 5654 ++++++++ src/cpu/blaze/math/dense/DenseIterator.h | 755 + src/cpu/blaze/math/dense/DenseMatrix.h | 1750 +++ src/cpu/blaze/math/dense/DenseVector.h | 648 + src/cpu/blaze/math/dense/DynamicMatrix.h | 6324 +++++++++ src/cpu/blaze/math/dense/DynamicVector.h | 2973 ++++ src/cpu/blaze/math/dense/Forward.h | 65 + src/cpu/blaze/math/dense/HybridMatrix.h | 6663 +++++++++ src/cpu/blaze/math/dense/HybridVector.h | 3015 ++++ src/cpu/blaze/math/dense/Inversion.h | 1126 ++ src/cpu/blaze/math/dense/LLH.h | 175 + src/cpu/blaze/math/dense/LQ.h | 246 + src/cpu/blaze/math/dense/LU.h | 329 + src/cpu/blaze/math/dense/QL.h | 247 + src/cpu/blaze/math/dense/QR.h | 246 + src/cpu/blaze/math/dense/RQ.h | 248 + src/cpu/blaze/math/dense/StaticMatrix.h | 6270 +++++++++ src/cpu/blaze/math/dense/StaticVector.h | 2842 ++++ src/cpu/blaze/math/expressions/AddExpr.h | 71 + src/cpu/blaze/math/expressions/Computation.h | 65 + src/cpu/blaze/math/expressions/CrossExpr.h | 71 + .../blaze/math/expressions/DMatDMatAddExpr.h | 1276 ++ .../blaze/math/expressions/DMatDMatMultExpr.h | 8100 +++++++++++ .../blaze/math/expressions/DMatDMatSubExpr.h | 1264 ++ .../blaze/math/expressions/DMatDVecMultExpr.h | 5453 ++++++++ src/cpu/blaze/math/expressions/DMatDetExpr.h | 428 + src/cpu/blaze/math/expressions/DMatEvalExpr.h | 1022 ++ .../blaze/math/expressions/DMatForEachExpr.h | 3080 +++++ src/cpu/blaze/math/expressions/DMatInvExpr.h | 617 + .../blaze/math/expressions/DMatSMatAddExpr.h | 1150 ++ .../blaze/math/expressions/DMatSMatMultExpr.h | 1766 +++ .../blaze/math/expressions/DMatSMatSubExpr.h | 1107 ++ .../blaze/math/expressions/DMatSVecMultExpr.h | 1031 ++ .../math/expressions/DMatScalarDivExpr.h | 1398 ++ .../math/expressions/DMatScalarMultExpr.h | 2943 ++++ .../blaze/math/expressions/DMatSerialExpr.h | 1040 ++ .../blaze/math/expressions/DMatTDMatAddExpr.h | 1270 ++ .../math/expressions/DMatTDMatMultExpr.h | 8114 +++++++++++ .../blaze/math/expressions/DMatTDMatSubExpr.h | 1264 ++ .../blaze/math/expressions/DMatTSMatAddExpr.h | 1080 ++ .../math/expressions/DMatTSMatMultExpr.h | 2075 +++ .../blaze/math/expressions/DMatTSMatSubExpr.h | 1031 ++ .../blaze/math/expressions/DMatTransExpr.h | 1296 ++ .../blaze/math/expressions/DMatTransposer.h | 1968 +++ .../blaze/math/expressions/DVecDVecAddExpr.h | 1150 ++ .../math/expressions/DVecDVecCrossExpr.h | 569 + .../blaze/math/expressions/DVecDVecDivExpr.h | 1151 ++ .../blaze/math/expressions/DVecDVecMultExpr.h | 1208 ++ .../blaze/math/expressions/DVecDVecSubExpr.h | 1142 ++ src/cpu/blaze/math/expressions/DVecEvalExpr.h | 867 ++ .../blaze/math/expressions/DVecForEachExpr.h | 2404 ++++ .../blaze/math/expressions/DVecSVecAddExpr.h | 946 ++ .../math/expressions/DVecSVecCrossExpr.h | 573 + .../blaze/math/expressions/DVecSVecMultExpr.h | 777 ++ .../blaze/math/expressions/DVecSVecSubExpr.h | 904 ++ .../math/expressions/DVecScalarDivExpr.h | 1314 ++ .../math/expressions/DVecScalarMultExpr.h | 2678 ++++ .../blaze/math/expressions/DVecSerialExpr.h | 889 ++ .../math/expressions/DVecTDVecMultExpr.h | 1792 +++ .../math/expressions/DVecTSVecMultExpr.h | 1326 ++ .../blaze/math/expressions/DVecTransExpr.h | 1120 ++ .../blaze/math/expressions/DVecTransposer.h | 833 ++ src/cpu/blaze/math/expressions/DenseMatrix.h | 76 + src/cpu/blaze/math/expressions/DenseVector.h | 76 + src/cpu/blaze/math/expressions/DivExpr.h | 71 + src/cpu/blaze/math/expressions/EvalExpr.h | 71 + src/cpu/blaze/math/expressions/Expression.h | 63 + src/cpu/blaze/math/expressions/ForEachExpr.h | 71 + src/cpu/blaze/math/expressions/Forward.h | 194 + src/cpu/blaze/math/expressions/MatEvalExpr.h | 71 + .../blaze/math/expressions/MatForEachExpr.h | 71 + src/cpu/blaze/math/expressions/MatInvExpr.h | 71 + .../blaze/math/expressions/MatMatAddExpr.h | 71 + .../blaze/math/expressions/MatMatMultExpr.h | 71 + .../blaze/math/expressions/MatMatSubExpr.h | 71 + .../blaze/math/expressions/MatScalarDivExpr.h | 71 + .../math/expressions/MatScalarMultExpr.h | 72 + .../blaze/math/expressions/MatSerialExpr.h | 71 + src/cpu/blaze/math/expressions/MatTransExpr.h | 71 + .../blaze/math/expressions/MatVecMultExpr.h | 72 + src/cpu/blaze/math/expressions/Matrix.h | 1331 ++ src/cpu/blaze/math/expressions/MultExpr.h | 72 + .../blaze/math/expressions/SMatDMatMultExpr.h | 2024 +++ .../blaze/math/expressions/SMatDMatSubExpr.h | 1097 ++ .../blaze/math/expressions/SMatDVecMultExpr.h | 949 ++ src/cpu/blaze/math/expressions/SMatEvalExpr.h | 1011 ++ .../blaze/math/expressions/SMatForEachExpr.h | 2591 ++++ .../blaze/math/expressions/SMatSMatAddExpr.h | 1058 ++ .../blaze/math/expressions/SMatSMatMultExpr.h | 1433 ++ .../blaze/math/expressions/SMatSMatSubExpr.h | 1056 ++ .../blaze/math/expressions/SMatSVecMultExpr.h | 1077 ++ .../math/expressions/SMatScalarDivExpr.h | 1201 ++ .../math/expressions/SMatScalarMultExpr.h | 2540 ++++ .../blaze/math/expressions/SMatSerialExpr.h | 1029 ++ .../math/expressions/SMatTDMatMultExpr.h | 2088 +++ .../blaze/math/expressions/SMatTDMatSubExpr.h | 1022 ++ .../blaze/math/expressions/SMatTSMatAddExpr.h | 1108 ++ .../math/expressions/SMatTSMatMultExpr.h | 1432 ++ .../blaze/math/expressions/SMatTSMatSubExpr.h | 1060 ++ .../blaze/math/expressions/SMatTransExpr.h | 1110 ++ .../blaze/math/expressions/SMatTransposer.h | 1149 ++ .../math/expressions/SVecDVecCrossExpr.h | 573 + .../blaze/math/expressions/SVecDVecDivExpr.h | 774 ++ .../blaze/math/expressions/SVecDVecMultExpr.h | 775 ++ .../blaze/math/expressions/SVecDVecSubExpr.h | 893 ++ src/cpu/blaze/math/expressions/SVecEvalExpr.h | 749 + .../blaze/math/expressions/SVecForEachExpr.h | 2059 +++ .../blaze/math/expressions/SVecSVecAddExpr.h | 728 + .../math/expressions/SVecSVecCrossExpr.h | 569 + .../blaze/math/expressions/SVecSVecMultExpr.h | 662 + .../blaze/math/expressions/SVecSVecSubExpr.h | 729 + .../math/expressions/SVecScalarDivExpr.h | 1038 ++ .../math/expressions/SVecScalarMultExpr.h | 2168 +++ .../blaze/math/expressions/SVecSerialExpr.h | 769 ++ .../math/expressions/SVecTDVecMultExpr.h | 1331 ++ .../math/expressions/SVecTSVecMultExpr.h | 846 ++ .../blaze/math/expressions/SVecTransExpr.h | 903 ++ .../blaze/math/expressions/SVecTransposer.h | 509 + src/cpu/blaze/math/expressions/SerialExpr.h | 71 + src/cpu/blaze/math/expressions/SparseMatrix.h | 76 + src/cpu/blaze/math/expressions/SparseVector.h | 76 + src/cpu/blaze/math/expressions/SubExpr.h | 71 + .../math/expressions/TDMatDMatMultExpr.h | 11474 ++++++++++++++++ .../math/expressions/TDMatDVecMultExpr.h | 4829 +++++++ .../blaze/math/expressions/TDMatSMatAddExpr.h | 1082 ++ .../math/expressions/TDMatSMatMultExpr.h | 2128 +++ .../blaze/math/expressions/TDMatSMatSubExpr.h | 1032 ++ .../math/expressions/TDMatSVecMultExpr.h | 1819 +++ .../math/expressions/TDMatTDMatMultExpr.h | 8119 +++++++++++ .../math/expressions/TDMatTSMatMultExpr.h | 2024 +++ .../math/expressions/TDVecDMatMultExpr.h | 4864 +++++++ .../math/expressions/TDVecDVecMultExpr.h | 261 + .../math/expressions/TDVecSMatMultExpr.h | 1037 ++ .../math/expressions/TDVecSVecMultExpr.h | 142 + .../math/expressions/TDVecTDMatMultExpr.h | 5439 ++++++++ .../math/expressions/TDVecTSMatMultExpr.h | 884 ++ .../math/expressions/TSMatDMatMultExpr.h | 2084 +++ .../blaze/math/expressions/TSMatDMatSubExpr.h | 1021 ++ .../math/expressions/TSMatDVecMultExpr.h | 1033 ++ .../math/expressions/TSMatSMatMultExpr.h | 1519 ++ .../blaze/math/expressions/TSMatSMatSubExpr.h | 1060 ++ .../math/expressions/TSMatSVecMultExpr.h | 896 ++ .../math/expressions/TSMatTDMatMultExpr.h | 2118 +++ .../math/expressions/TSMatTSMatAddExpr.h | 1066 ++ .../math/expressions/TSMatTSMatMultExpr.h | 1439 ++ .../math/expressions/TSMatTSMatSubExpr.h | 1064 ++ .../math/expressions/TSVecDMatMultExpr.h | 1839 +++ .../math/expressions/TSVecDVecMultExpr.h | 142 + .../math/expressions/TSVecSMatMultExpr.h | 927 ++ .../math/expressions/TSVecSVecMultExpr.h | 215 + .../math/expressions/TSVecTDMatMultExpr.h | 981 ++ .../math/expressions/TSVecTSMatMultExpr.h | 1052 ++ .../blaze/math/expressions/TVecMatMultExpr.h | 72 + src/cpu/blaze/math/expressions/TransExpr.h | 71 + src/cpu/blaze/math/expressions/VecEvalExpr.h | 71 + .../blaze/math/expressions/VecForEachExpr.h | 71 + .../blaze/math/expressions/VecScalarDivExpr.h | 71 + .../math/expressions/VecScalarMultExpr.h | 72 + .../blaze/math/expressions/VecSerialExpr.h | 71 + .../blaze/math/expressions/VecTVecMultExpr.h | 72 + src/cpu/blaze/math/expressions/VecTransExpr.h | 71 + .../blaze/math/expressions/VecVecAddExpr.h | 71 + .../blaze/math/expressions/VecVecDivExpr.h | 71 + .../blaze/math/expressions/VecVecMultExpr.h | 71 + .../blaze/math/expressions/VecVecSubExpr.h | 71 + src/cpu/blaze/math/expressions/Vector.h | 770 ++ src/cpu/blaze/math/expressions/View.h | 70 + src/cpu/blaze/math/functors/Abs.h | 104 + src/cpu/blaze/math/functors/Acos.h | 104 + src/cpu/blaze/math/functors/Acosh.h | 104 + src/cpu/blaze/math/functors/Asin.h | 104 + src/cpu/blaze/math/functors/Asinh.h | 104 + src/cpu/blaze/math/functors/Atan.h | 104 + src/cpu/blaze/math/functors/Atanh.h | 104 + src/cpu/blaze/math/functors/CTrans.h | 77 + src/cpu/blaze/math/functors/Cbrt.h | 104 + src/cpu/blaze/math/functors/Ceil.h | 104 + src/cpu/blaze/math/functors/Conj.h | 104 + src/cpu/blaze/math/functors/Cos.h | 104 + src/cpu/blaze/math/functors/Cosh.h | 104 + src/cpu/blaze/math/functors/Erf.h | 104 + src/cpu/blaze/math/functors/Erfc.h | 104 + src/cpu/blaze/math/functors/Eval.h | 77 + src/cpu/blaze/math/functors/Exp.h | 104 + src/cpu/blaze/math/functors/Floor.h | 104 + src/cpu/blaze/math/functors/Forward.h | 83 + src/cpu/blaze/math/functors/Functors.h | 51 + src/cpu/blaze/math/functors/Imag.h | 78 + src/cpu/blaze/math/functors/Inv.h | 78 + src/cpu/blaze/math/functors/InvCbrt.h | 104 + src/cpu/blaze/math/functors/InvSqrt.h | 104 + src/cpu/blaze/math/functors/Log.h | 104 + src/cpu/blaze/math/functors/Log10.h | 104 + src/cpu/blaze/math/functors/Pow.h | 139 + src/cpu/blaze/math/functors/Real.h | 78 + src/cpu/blaze/math/functors/Serial.h | 77 + src/cpu/blaze/math/functors/Sin.h | 104 + src/cpu/blaze/math/functors/Sinh.h | 104 + src/cpu/blaze/math/functors/Sqrt.h | 104 + src/cpu/blaze/math/functors/Tan.h | 104 + src/cpu/blaze/math/functors/Tanh.h | 104 + src/cpu/blaze/math/functors/Trans.h | 77 + src/cpu/blaze/math/lapack/LAPACK.h | 79 + src/cpu/blaze/math/lapack/clapack/gelqf.h | 326 + src/cpu/blaze/math/lapack/clapack/geqlf.h | 330 + src/cpu/blaze/math/lapack/clapack/geqp3.h | 194 + src/cpu/blaze/math/lapack/clapack/geqrf.h | 326 + src/cpu/blaze/math/lapack/clapack/gerqf.h | 330 + src/cpu/blaze/math/lapack/clapack/gesv.h | 294 + src/cpu/blaze/math/lapack/clapack/getrf.h | 272 + src/cpu/blaze/math/lapack/clapack/getri.h | 270 + src/cpu/blaze/math/lapack/clapack/getrs.h | 288 + src/cpu/blaze/math/lapack/clapack/hesv.h | 206 + src/cpu/blaze/math/lapack/clapack/hetrf.h | 204 + src/cpu/blaze/math/lapack/clapack/hetri.h | 172 + src/cpu/blaze/math/lapack/clapack/hetrs.h | 176 + src/cpu/blaze/math/lapack/clapack/orglq.h | 162 + src/cpu/blaze/math/lapack/clapack/orgql.h | 162 + src/cpu/blaze/math/lapack/clapack/orgqr.h | 162 + src/cpu/blaze/math/lapack/clapack/orgrq.h | 162 + src/cpu/blaze/math/lapack/clapack/ormlq.h | 190 + src/cpu/blaze/math/lapack/clapack/ormql.h | 190 + src/cpu/blaze/math/lapack/clapack/ormqr.h | 190 + src/cpu/blaze/math/lapack/clapack/ormrq.h | 190 + src/cpu/blaze/math/lapack/clapack/posv.h | 302 + src/cpu/blaze/math/lapack/clapack/potrf.h | 272 + src/cpu/blaze/math/lapack/clapack/potri.h | 244 + src/cpu/blaze/math/lapack/clapack/potrs.h | 256 + src/cpu/blaze/math/lapack/clapack/sysv.h | 326 + src/cpu/blaze/math/lapack/clapack/sytrf.h | 322 + src/cpu/blaze/math/lapack/clapack/sytri.h | 254 + src/cpu/blaze/math/lapack/clapack/sytrs.h | 268 + src/cpu/blaze/math/lapack/clapack/trsv.h | 270 + src/cpu/blaze/math/lapack/clapack/trtri.h | 244 + src/cpu/blaze/math/lapack/clapack/trtrs.h | 286 + src/cpu/blaze/math/lapack/clapack/unglq.h | 172 + src/cpu/blaze/math/lapack/clapack/ungql.h | 172 + src/cpu/blaze/math/lapack/clapack/ungqr.h | 172 + src/cpu/blaze/math/lapack/clapack/ungrq.h | 172 + src/cpu/blaze/math/lapack/clapack/unmlq.h | 212 + src/cpu/blaze/math/lapack/clapack/unmql.h | 212 + src/cpu/blaze/math/lapack/clapack/unmqr.h | 212 + src/cpu/blaze/math/lapack/clapack/unmrq.h | 212 + src/cpu/blaze/math/lapack/gelqf.h | 152 + src/cpu/blaze/math/lapack/geqlf.h | 153 + src/cpu/blaze/math/lapack/geqp3.h | 45 + src/cpu/blaze/math/lapack/geqrf.h | 152 + src/cpu/blaze/math/lapack/gerqf.h | 153 + src/cpu/blaze/math/lapack/gesv.h | 273 + src/cpu/blaze/math/lapack/getrf.h | 147 + src/cpu/blaze/math/lapack/getri.h | 147 + src/cpu/blaze/math/lapack/getrs.h | 336 + src/cpu/blaze/math/lapack/hesv.h | 314 + src/cpu/blaze/math/lapack/hetrf.h | 161 + src/cpu/blaze/math/lapack/hetri.h | 159 + src/cpu/blaze/math/lapack/hetrs.h | 343 + src/cpu/blaze/math/lapack/orglq.h | 154 + src/cpu/blaze/math/lapack/orgql.h | 157 + src/cpu/blaze/math/lapack/orgqr.h | 154 + src/cpu/blaze/math/lapack/orgrq.h | 157 + src/cpu/blaze/math/lapack/ormlq.h | 201 + src/cpu/blaze/math/lapack/ormql.h | 202 + src/cpu/blaze/math/lapack/ormqr.h | 201 + src/cpu/blaze/math/lapack/ormrq.h | 202 + src/cpu/blaze/math/lapack/posv.h | 299 + src/cpu/blaze/math/lapack/potrf.h | 157 + src/cpu/blaze/math/lapack/potri.h | 154 + src/cpu/blaze/math/lapack/potrs.h | 336 + src/cpu/blaze/math/lapack/sysv.h | 314 + src/cpu/blaze/math/lapack/sytrf.h | 161 + src/cpu/blaze/math/lapack/sytri.h | 158 + src/cpu/blaze/math/lapack/sytrs.h | 343 + src/cpu/blaze/math/lapack/trsv.h | 210 + src/cpu/blaze/math/lapack/trtri.h | 159 + src/cpu/blaze/math/lapack/trtrs.h | 362 + src/cpu/blaze/math/lapack/unglq.h | 156 + src/cpu/blaze/math/lapack/ungql.h | 159 + src/cpu/blaze/math/lapack/ungqr.h | 156 + src/cpu/blaze/math/lapack/ungrq.h | 158 + src/cpu/blaze/math/lapack/unmlq.h | 195 + src/cpu/blaze/math/lapack/unmql.h | 196 + src/cpu/blaze/math/lapack/unmqr.h | 195 + src/cpu/blaze/math/lapack/unmrq.h | 196 + src/cpu/blaze/math/proxy/ComplexProxy.h | 227 + src/cpu/blaze/math/proxy/DefaultProxy.h | 119 + src/cpu/blaze/math/proxy/DenseMatrixProxy.h | 1109 ++ src/cpu/blaze/math/proxy/DenseVectorProxy.h | 757 + src/cpu/blaze/math/proxy/Forward.h | 57 + src/cpu/blaze/math/proxy/Proxy.h | 1793 +++ src/cpu/blaze/math/proxy/SparseMatrixProxy.h | 1339 ++ src/cpu/blaze/math/proxy/SparseVectorProxy.h | 886 ++ .../math/serialization/MatrixSerializer.h | 1298 ++ .../blaze/math/serialization/Serialization.h | 126 + .../math/serialization/TypeValueMapping.h | 180 + .../math/serialization/VectorSerializer.h | 887 ++ src/cpu/blaze/math/shims/Abs.h | 63 + src/cpu/blaze/math/shims/Acos.h | 63 + src/cpu/blaze/math/shims/Acosh.h | 63 + src/cpu/blaze/math/shims/Asin.h | 63 + src/cpu/blaze/math/shims/Asinh.h | 63 + src/cpu/blaze/math/shims/Atan.h | 63 + src/cpu/blaze/math/shims/Atanh.h | 63 + src/cpu/blaze/math/shims/Cbrt.h | 63 + src/cpu/blaze/math/shims/Ceil.h | 63 + src/cpu/blaze/math/shims/Clear.h | 73 + src/cpu/blaze/math/shims/Conjugate.h | 203 + src/cpu/blaze/math/shims/Cos.h | 63 + src/cpu/blaze/math/shims/Cosh.h | 63 + src/cpu/blaze/math/shims/Equal.h | 383 + src/cpu/blaze/math/shims/Erf.h | 63 + src/cpu/blaze/math/shims/Erfc.h | 63 + src/cpu/blaze/math/shims/Exp.h | 63 + src/cpu/blaze/math/shims/Floor.h | 63 + src/cpu/blaze/math/shims/Imaginary.h | 94 + src/cpu/blaze/math/shims/InvCbrt.h | 79 + src/cpu/blaze/math/shims/InvSqrt.h | 100 + src/cpu/blaze/math/shims/Invert.h | 318 + src/cpu/blaze/math/shims/IsDefault.h | 168 + src/cpu/blaze/math/shims/IsDivisor.h | 89 + src/cpu/blaze/math/shims/IsNaN.h | 87 + src/cpu/blaze/math/shims/IsOne.h | 108 + src/cpu/blaze/math/shims/IsReal.h | 109 + src/cpu/blaze/math/shims/IsZero.h | 108 + src/cpu/blaze/math/shims/Log.h | 63 + src/cpu/blaze/math/shims/Log10.h | 63 + src/cpu/blaze/math/shims/Pow.h | 63 + src/cpu/blaze/math/shims/Real.h | 91 + src/cpu/blaze/math/shims/Reset.h | 73 + src/cpu/blaze/math/shims/Serial.h | 79 + src/cpu/blaze/math/shims/Shims.h | 51 + src/cpu/blaze/math/shims/Sin.h | 63 + src/cpu/blaze/math/shims/Sinh.h | 63 + src/cpu/blaze/math/shims/Sqrt.h | 63 + src/cpu/blaze/math/shims/Square.h | 75 + src/cpu/blaze/math/shims/Tan.h | 63 + src/cpu/blaze/math/shims/Tanh.h | 63 + src/cpu/blaze/math/simd/Abs.h | 177 + src/cpu/blaze/math/simd/Acos.h | 123 + src/cpu/blaze/math/simd/Acosh.h | 123 + src/cpu/blaze/math/simd/Addition.h | 573 + src/cpu/blaze/math/simd/Asin.h | 123 + src/cpu/blaze/math/simd/Asinh.h | 123 + src/cpu/blaze/math/simd/Atan.h | 123 + src/cpu/blaze/math/simd/Atanh.h | 123 + src/cpu/blaze/math/simd/BasicTypes.h | 1348 ++ src/cpu/blaze/math/simd/Cbrt.h | 123 + src/cpu/blaze/math/simd/Ceil.h | 125 + src/cpu/blaze/math/simd/Conj.h | 298 + src/cpu/blaze/math/simd/Cos.h | 123 + src/cpu/blaze/math/simd/Cosh.h | 123 + src/cpu/blaze/math/simd/DerivedTypes.h | 216 + src/cpu/blaze/math/simd/Division.h | 293 + src/cpu/blaze/math/simd/Erf.h | 123 + src/cpu/blaze/math/simd/Erfc.h | 125 + src/cpu/blaze/math/simd/Exp.h | 123 + src/cpu/blaze/math/simd/FMA.h | 1476 ++ src/cpu/blaze/math/simd/Floor.h | 125 + src/cpu/blaze/math/simd/Functions.h | 83 + src/cpu/blaze/math/simd/InvCbrt.h | 115 + src/cpu/blaze/math/simd/InvSqrt.h | 123 + src/cpu/blaze/math/simd/Loada.h | 465 + src/cpu/blaze/math/simd/Loadu.h | 457 + src/cpu/blaze/math/simd/Log.h | 123 + src/cpu/blaze/math/simd/Log10.h | 123 + src/cpu/blaze/math/simd/Multiplication.h | 881 ++ src/cpu/blaze/math/simd/Pow.h | 125 + src/cpu/blaze/math/simd/Reduction.h | 364 + src/cpu/blaze/math/simd/SIMD.h | 51 + src/cpu/blaze/math/simd/SIMDPack.h | 89 + src/cpu/blaze/math/simd/SIMDTrait.h | 320 + src/cpu/blaze/math/simd/Set.h | 417 + src/cpu/blaze/math/simd/Setzero.h | 361 + src/cpu/blaze/math/simd/Sin.h | 123 + src/cpu/blaze/math/simd/Sinh.h | 123 + src/cpu/blaze/math/simd/Sqrt.h | 123 + src/cpu/blaze/math/simd/Storea.h | 477 + src/cpu/blaze/math/simd/Storeu.h | 455 + src/cpu/blaze/math/simd/Stream.h | 429 + src/cpu/blaze/math/simd/Subtraction.h | 573 + src/cpu/blaze/math/simd/Tan.h | 123 + src/cpu/blaze/math/simd/Tanh.h | 123 + src/cpu/blaze/math/smp/DenseMatrix.h | 53 + src/cpu/blaze/math/smp/DenseVector.h | 53 + src/cpu/blaze/math/smp/Functions.h | 53 + src/cpu/blaze/math/smp/ParallelSection.h | 252 + src/cpu/blaze/math/smp/SMP.h | 51 + src/cpu/blaze/math/smp/SerialSection.h | 268 + src/cpu/blaze/math/smp/SparseMatrix.h | 45 + src/cpu/blaze/math/smp/SparseVector.h | 45 + src/cpu/blaze/math/smp/default/DenseMatrix.h | 193 + src/cpu/blaze/math/smp/default/DenseVector.h | 253 + src/cpu/blaze/math/smp/default/Functions.h | 154 + src/cpu/blaze/math/smp/default/SparseMatrix.h | 171 + src/cpu/blaze/math/smp/default/SparseVector.h | 200 + src/cpu/blaze/math/smp/openmp/DenseMatrix.h | 1165 ++ src/cpu/blaze/math/smp/openmp/DenseVector.h | 1129 ++ src/cpu/blaze/math/smp/openmp/Functions.h | 154 + src/cpu/blaze/math/smp/threads/DenseMatrix.h | 1182 ++ src/cpu/blaze/math/smp/threads/DenseVector.h | 1145 ++ src/cpu/blaze/math/smp/threads/Functions.h | 156 + .../blaze/math/smp/threads/ThreadBackend.h | 665 + src/cpu/blaze/math/sparse/CompressedMatrix.h | 5650 ++++++++ src/cpu/blaze/math/sparse/CompressedVector.h | 2655 ++++ src/cpu/blaze/math/sparse/Forward.h | 52 + src/cpu/blaze/math/sparse/MatrixAccessProxy.h | 694 + src/cpu/blaze/math/sparse/SparseElement.h | 63 + src/cpu/blaze/math/sparse/SparseMatrix.h | 1589 +++ src/cpu/blaze/math/sparse/SparseVector.h | 488 + src/cpu/blaze/math/sparse/ValueIndexPair.h | 337 + src/cpu/blaze/math/sparse/VectorAccessProxy.h | 673 + src/cpu/blaze/math/traits/AddExprTrait.h | 224 + src/cpu/blaze/math/traits/AddTrait.h | 236 + src/cpu/blaze/math/traits/CTransExprTrait.h | 148 + src/cpu/blaze/math/traits/ColumnExprTrait.h | 138 + src/cpu/blaze/math/traits/ColumnTrait.h | 157 + src/cpu/blaze/math/traits/CrossExprTrait.h | 155 + src/cpu/blaze/math/traits/CrossTrait.h | 140 + .../blaze/math/traits/DMatCTransExprTrait.h | 125 + .../blaze/math/traits/DMatDMatAddExprTrait.h | 121 + .../blaze/math/traits/DMatDMatMultExprTrait.h | 121 + .../blaze/math/traits/DMatDMatSubExprTrait.h | 121 + .../blaze/math/traits/DMatDVecMultExprTrait.h | 124 + src/cpu/blaze/math/traits/DMatEvalExprTrait.h | 116 + .../blaze/math/traits/DMatForEachExprTrait.h | 119 + src/cpu/blaze/math/traits/DMatInvExprTrait.h | 116 + .../blaze/math/traits/DMatSMatAddExprTrait.h | 123 + .../blaze/math/traits/DMatSMatMultExprTrait.h | 124 + .../blaze/math/traits/DMatSMatSubExprTrait.h | 123 + .../blaze/math/traits/DMatSVecMultExprTrait.h | 128 + .../math/traits/DMatScalarDivExprTrait.h | 172 + .../math/traits/DMatScalarMultExprTrait.h | 169 + .../blaze/math/traits/DMatSerialExprTrait.h | 116 + .../blaze/math/traits/DMatTDMatAddExprTrait.h | 131 + .../math/traits/DMatTDMatMultExprTrait.h | 124 + .../blaze/math/traits/DMatTDMatSubExprTrait.h | 131 + .../blaze/math/traits/DMatTSMatAddExprTrait.h | 125 + .../math/traits/DMatTSMatMultExprTrait.h | 124 + .../blaze/math/traits/DMatTSMatSubExprTrait.h | 124 + .../blaze/math/traits/DMatTransExprTrait.h | 116 + .../blaze/math/traits/DVecCTransExprTrait.h | 125 + .../blaze/math/traits/DVecDVecAddExprTrait.h | 122 + .../math/traits/DVecDVecCrossExprTrait.h | 122 + .../blaze/math/traits/DVecDVecDivExprTrait.h | 122 + .../blaze/math/traits/DVecDVecMultExprTrait.h | 122 + .../blaze/math/traits/DVecDVecSubExprTrait.h | 122 + src/cpu/blaze/math/traits/DVecEvalExprTrait.h | 116 + .../blaze/math/traits/DVecForEachExprTrait.h | 119 + .../blaze/math/traits/DVecSVecAddExprTrait.h | 123 + .../math/traits/DVecSVecCrossExprTrait.h | 123 + .../blaze/math/traits/DVecSVecMultExprTrait.h | 123 + .../blaze/math/traits/DVecSVecSubExprTrait.h | 123 + .../math/traits/DVecScalarDivExprTrait.h | 172 + .../math/traits/DVecScalarMultExprTrait.h | 169 + .../blaze/math/traits/DVecSerialExprTrait.h | 116 + .../math/traits/DVecTDVecMultExprTrait.h | 124 + .../math/traits/DVecTSVecMultExprTrait.h | 125 + .../blaze/math/traits/DVecTransExprTrait.h | 116 + src/cpu/blaze/math/traits/DerestrictTrait.h | 115 + src/cpu/blaze/math/traits/DivExprTrait.h | 201 + src/cpu/blaze/math/traits/DivTrait.h | 236 + src/cpu/blaze/math/traits/EvalExprTrait.h | 147 + src/cpu/blaze/math/traits/ForEachExprTrait.h | 149 + src/cpu/blaze/math/traits/ForEachTrait.h | 151 + src/cpu/blaze/math/traits/ImagTrait.h | 157 + src/cpu/blaze/math/traits/InvExprTrait.h | 139 + src/cpu/blaze/math/traits/MathTrait.h | 775 ++ src/cpu/blaze/math/traits/MultExprTrait.h | 349 + src/cpu/blaze/math/traits/MultTrait.h | 236 + src/cpu/blaze/math/traits/RealTrait.h | 157 + src/cpu/blaze/math/traits/RowExprTrait.h | 139 + src/cpu/blaze/math/traits/RowTrait.h | 157 + .../blaze/math/traits/SMatCTransExprTrait.h | 125 + .../blaze/math/traits/SMatDMatAddExprTrait.h | 123 + .../blaze/math/traits/SMatDMatMultExprTrait.h | 123 + .../blaze/math/traits/SMatDMatSubExprTrait.h | 123 + .../blaze/math/traits/SMatDVecMultExprTrait.h | 124 + src/cpu/blaze/math/traits/SMatEvalExprTrait.h | 116 + .../blaze/math/traits/SMatForEachExprTrait.h | 119 + .../blaze/math/traits/SMatSMatAddExprTrait.h | 121 + .../blaze/math/traits/SMatSMatMultExprTrait.h | 121 + .../blaze/math/traits/SMatSMatSubExprTrait.h | 121 + .../blaze/math/traits/SMatSVecMultExprTrait.h | 128 + .../math/traits/SMatScalarDivExprTrait.h | 172 + .../math/traits/SMatScalarMultExprTrait.h | 169 + .../blaze/math/traits/SMatSerialExprTrait.h | 116 + .../blaze/math/traits/SMatTDMatAddExprTrait.h | 124 + .../math/traits/SMatTDMatMultExprTrait.h | 125 + .../blaze/math/traits/SMatTDMatSubExprTrait.h | 125 + .../blaze/math/traits/SMatTSMatAddExprTrait.h | 124 + .../math/traits/SMatTSMatMultExprTrait.h | 124 + .../blaze/math/traits/SMatTSMatSubExprTrait.h | 124 + .../blaze/math/traits/SMatTransExprTrait.h | 116 + .../blaze/math/traits/SVecCTransExprTrait.h | 125 + .../blaze/math/traits/SVecDVecAddExprTrait.h | 123 + .../math/traits/SVecDVecCrossExprTrait.h | 124 + .../blaze/math/traits/SVecDVecDivExprTrait.h | 124 + .../blaze/math/traits/SVecDVecMultExprTrait.h | 124 + .../blaze/math/traits/SVecDVecSubExprTrait.h | 123 + src/cpu/blaze/math/traits/SVecEvalExprTrait.h | 116 + .../blaze/math/traits/SVecForEachExprTrait.h | 119 + .../blaze/math/traits/SVecSVecAddExprTrait.h | 122 + .../math/traits/SVecSVecCrossExprTrait.h | 122 + .../blaze/math/traits/SVecSVecMultExprTrait.h | 122 + .../blaze/math/traits/SVecSVecSubExprTrait.h | 122 + .../math/traits/SVecScalarDivExprTrait.h | 172 + .../math/traits/SVecScalarMultExprTrait.h | 169 + .../blaze/math/traits/SVecSerialExprTrait.h | 116 + .../math/traits/SVecTDVecMultExprTrait.h | 125 + .../math/traits/SVecTSVecMultExprTrait.h | 124 + .../blaze/math/traits/SVecTransExprTrait.h | 116 + src/cpu/blaze/math/traits/SerialExprTrait.h | 147 + src/cpu/blaze/math/traits/SubExprTrait.h | 225 + src/cpu/blaze/math/traits/SubTrait.h | 236 + .../blaze/math/traits/SubmatrixExprTrait.h | 138 + src/cpu/blaze/math/traits/SubmatrixTrait.h | 158 + .../blaze/math/traits/SubvectorExprTrait.h | 138 + src/cpu/blaze/math/traits/SubvectorTrait.h | 160 + .../blaze/math/traits/TDMatCTransExprTrait.h | 125 + .../blaze/math/traits/TDMatDMatAddExprTrait.h | 130 + .../math/traits/TDMatDMatMultExprTrait.h | 124 + .../blaze/math/traits/TDMatDMatSubExprTrait.h | 130 + .../math/traits/TDMatDVecMultExprTrait.h | 125 + .../blaze/math/traits/TDMatEvalExprTrait.h | 116 + .../blaze/math/traits/TDMatForEachExprTrait.h | 119 + src/cpu/blaze/math/traits/TDMatInvExprTrait.h | 116 + .../blaze/math/traits/TDMatSMatAddExprTrait.h | 124 + .../math/traits/TDMatSMatMultExprTrait.h | 125 + .../blaze/math/traits/TDMatSMatSubExprTrait.h | 125 + .../math/traits/TDMatSVecMultExprTrait.h | 125 + .../math/traits/TDMatScalarDivExprTrait.h | 172 + .../math/traits/TDMatScalarMultExprTrait.h | 169 + .../blaze/math/traits/TDMatSerialExprTrait.h | 116 + .../math/traits/TDMatTDMatAddExprTrait.h | 123 + .../math/traits/TDMatTDMatMultExprTrait.h | 123 + .../math/traits/TDMatTDMatSubExprTrait.h | 123 + .../math/traits/TDMatTSMatAddExprTrait.h | 125 + .../math/traits/TDMatTSMatMultExprTrait.h | 125 + .../math/traits/TDMatTSMatSubExprTrait.h | 125 + .../blaze/math/traits/TDMatTransExprTrait.h | 116 + .../blaze/math/traits/TDVecCTransExprTrait.h | 125 + .../math/traits/TDVecDMatMultExprTrait.h | 124 + .../math/traits/TDVecDVecMultExprTrait.h | 157 + .../blaze/math/traits/TDVecEvalExprTrait.h | 116 + .../blaze/math/traits/TDVecForEachExprTrait.h | 119 + .../math/traits/TDVecSMatMultExprTrait.h | 128 + .../math/traits/TDVecSVecMultExprTrait.h | 158 + .../math/traits/TDVecScalarDivExprTrait.h | 172 + .../math/traits/TDVecScalarMultExprTrait.h | 169 + .../blaze/math/traits/TDVecSerialExprTrait.h | 116 + .../math/traits/TDVecTDMatMultExprTrait.h | 125 + .../math/traits/TDVecTDVecAddExprTrait.h | 123 + .../math/traits/TDVecTDVecCrossExprTrait.h | 122 + .../math/traits/TDVecTDVecDivExprTrait.h | 123 + .../math/traits/TDVecTDVecMultExprTrait.h | 123 + .../math/traits/TDVecTDVecSubExprTrait.h | 123 + .../math/traits/TDVecTSMatMultExprTrait.h | 125 + .../math/traits/TDVecTSVecAddExprTrait.h | 124 + .../math/traits/TDVecTSVecCrossExprTrait.h | 123 + .../math/traits/TDVecTSVecMultExprTrait.h | 124 + .../math/traits/TDVecTSVecSubExprTrait.h | 124 + .../blaze/math/traits/TDVecTransExprTrait.h | 116 + .../blaze/math/traits/TSMatCTransExprTrait.h | 125 + .../blaze/math/traits/TSMatDMatAddExprTrait.h | 124 + .../math/traits/TSMatDMatMultExprTrait.h | 125 + .../blaze/math/traits/TSMatDMatSubExprTrait.h | 124 + .../math/traits/TSMatDVecMultExprTrait.h | 129 + .../blaze/math/traits/TSMatEvalExprTrait.h | 116 + .../blaze/math/traits/TSMatForEachExprTrait.h | 119 + .../blaze/math/traits/TSMatSMatAddExprTrait.h | 123 + .../math/traits/TSMatSMatMultExprTrait.h | 124 + .../blaze/math/traits/TSMatSMatSubExprTrait.h | 124 + .../math/traits/TSMatSVecMultExprTrait.h | 125 + .../math/traits/TSMatScalarDivExprTrait.h | 172 + .../math/traits/TSMatScalarMultExprTrait.h | 169 + .../blaze/math/traits/TSMatSerialExprTrait.h | 116 + .../math/traits/TSMatTDMatAddExprTrait.h | 125 + .../math/traits/TSMatTDMatMultExprTrait.h | 125 + .../math/traits/TSMatTDMatSubExprTrait.h | 125 + .../math/traits/TSMatTSMatAddExprTrait.h | 123 + .../math/traits/TSMatTSMatMultExprTrait.h | 123 + .../math/traits/TSMatTSMatSubExprTrait.h | 123 + .../blaze/math/traits/TSMatTransExprTrait.h | 116 + .../blaze/math/traits/TSVecCTransExprTrait.h | 125 + .../math/traits/TSVecDMatMultExprTrait.h | 124 + .../math/traits/TSVecDVecMultExprTrait.h | 158 + .../blaze/math/traits/TSVecEvalExprTrait.h | 116 + .../blaze/math/traits/TSVecForEachExprTrait.h | 119 + .../math/traits/TSVecSMatMultExprTrait.h | 124 + .../math/traits/TSVecSVecMultExprTrait.h | 157 + .../math/traits/TSVecScalarDivExprTrait.h | 172 + .../math/traits/TSVecScalarMultExprTrait.h | 169 + .../blaze/math/traits/TSVecSerialExprTrait.h | 116 + .../math/traits/TSVecTDMatMultExprTrait.h | 129 + .../math/traits/TSVecTDVecAddExprTrait.h | 124 + .../math/traits/TSVecTDVecCrossExprTrait.h | 123 + .../math/traits/TSVecTDVecDivExprTrait.h | 124 + .../math/traits/TSVecTDVecMultExprTrait.h | 124 + .../math/traits/TSVecTDVecSubExprTrait.h | 124 + .../math/traits/TSVecTSMatMultExprTrait.h | 129 + .../math/traits/TSVecTSVecAddExprTrait.h | 123 + .../math/traits/TSVecTSVecCrossExprTrait.h | 122 + .../math/traits/TSVecTSVecMultExprTrait.h | 123 + .../math/traits/TSVecTSVecSubExprTrait.h | 123 + .../blaze/math/traits/TSVecTransExprTrait.h | 116 + src/cpu/blaze/math/traits/Traits.h | 51 + src/cpu/blaze/math/traits/TransExprTrait.h | 148 + .../blaze/math/typetraits/AreSIMDCombinable.h | 128 + src/cpu/blaze/math/typetraits/Columns.h | 118 + .../math/typetraits/HasConstDataAccess.h | 117 + .../math/typetraits/HasMutableDataAccess.h | 117 + src/cpu/blaze/math/typetraits/HasSIMDAbs.h | 116 + src/cpu/blaze/math/typetraits/HasSIMDAcos.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDAcosh.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDAdd.h | 168 + src/cpu/blaze/math/typetraits/HasSIMDAsin.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDAsinh.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDAtan.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDAtanh.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDCbrt.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDCeil.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDConj.h | 112 + src/cpu/blaze/math/typetraits/HasSIMDCos.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDCosh.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDDiv.h | 150 + src/cpu/blaze/math/typetraits/HasSIMDErf.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDErfc.h | 116 + src/cpu/blaze/math/typetraits/HasSIMDExp.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDFloor.h | 115 + .../blaze/math/typetraits/HasSIMDInvCbrt.h | 113 + .../blaze/math/typetraits/HasSIMDInvSqrt.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDLog.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDLog10.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDMult.h | 168 + src/cpu/blaze/math/typetraits/HasSIMDPow.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDSin.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDSinh.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDSqrt.h | 122 + src/cpu/blaze/math/typetraits/HasSIMDSub.h | 169 + src/cpu/blaze/math/typetraits/HasSIMDTan.h | 115 + src/cpu/blaze/math/typetraits/HasSIMDTanh.h | 115 + src/cpu/blaze/math/typetraits/IsAdaptor.h | 130 + src/cpu/blaze/math/typetraits/IsAddExpr.h | 78 + src/cpu/blaze/math/typetraits/IsAligned.h | 129 + .../blaze/math/typetraits/IsBLASCompatible.h | 87 + src/cpu/blaze/math/typetraits/IsColumn.h | 139 + .../math/typetraits/IsColumnMajorMatrix.h | 90 + .../blaze/math/typetraits/IsColumnVector.h | 87 + src/cpu/blaze/math/typetraits/IsComputation.h | 79 + src/cpu/blaze/math/typetraits/IsCrossExpr.h | 78 + src/cpu/blaze/math/typetraits/IsCustom.h | 126 + src/cpu/blaze/math/typetraits/IsDenseMatrix.h | 86 + src/cpu/blaze/math/typetraits/IsDenseVector.h | 86 + src/cpu/blaze/math/typetraits/IsDiagonal.h | 132 + src/cpu/blaze/math/typetraits/IsDivExpr.h | 79 + src/cpu/blaze/math/typetraits/IsEvalExpr.h | 77 + src/cpu/blaze/math/typetraits/IsExpression.h | 78 + src/cpu/blaze/math/typetraits/IsForEachExpr.h | 78 + src/cpu/blaze/math/typetraits/IsGeneral.h | 133 + src/cpu/blaze/math/typetraits/IsHermitian.h | 127 + src/cpu/blaze/math/typetraits/IsIdentity.h | 132 + src/cpu/blaze/math/typetraits/IsInvertible.h | 93 + src/cpu/blaze/math/typetraits/IsLower.h | 130 + src/cpu/blaze/math/typetraits/IsMatEvalExpr.h | 78 + .../blaze/math/typetraits/IsMatForEachExpr.h | 78 + src/cpu/blaze/math/typetraits/IsMatInvExpr.h | 78 + .../blaze/math/typetraits/IsMatMatAddExpr.h | 78 + .../blaze/math/typetraits/IsMatMatMultExpr.h | 80 + .../blaze/math/typetraits/IsMatMatSubExpr.h | 79 + .../math/typetraits/IsMatScalarDivExpr.h | 79 + .../math/typetraits/IsMatScalarMultExpr.h | 80 + .../blaze/math/typetraits/IsMatSerialExpr.h | 78 + .../blaze/math/typetraits/IsMatTransExpr.h | 78 + .../blaze/math/typetraits/IsMatVecMultExpr.h | 80 + src/cpu/blaze/math/typetraits/IsMatrix.h | 86 + src/cpu/blaze/math/typetraits/IsMultExpr.h | 80 + .../blaze/math/typetraits/IsNumericMatrix.h | 93 + .../blaze/math/typetraits/IsNumericVector.h | 93 + src/cpu/blaze/math/typetraits/IsOpposedView.h | 123 + src/cpu/blaze/math/typetraits/IsPadded.h | 118 + src/cpu/blaze/math/typetraits/IsProxy.h | 116 + src/cpu/blaze/math/typetraits/IsResizable.h | 117 + src/cpu/blaze/math/typetraits/IsRestricted.h | 124 + src/cpu/blaze/math/typetraits/IsRow.h | 139 + .../blaze/math/typetraits/IsRowMajorMatrix.h | 90 + src/cpu/blaze/math/typetraits/IsRowVector.h | 87 + src/cpu/blaze/math/typetraits/IsSIMDEnabled.h | 106 + src/cpu/blaze/math/typetraits/IsSIMDPack.h | 121 + .../blaze/math/typetraits/IsSMPAssignable.h | 125 + src/cpu/blaze/math/typetraits/IsSerialExpr.h | 78 + .../blaze/math/typetraits/IsSparseElement.h | 78 + .../blaze/math/typetraits/IsSparseMatrix.h | 86 + .../blaze/math/typetraits/IsSparseVector.h | 86 + src/cpu/blaze/math/typetraits/IsSquare.h | 130 + .../blaze/math/typetraits/IsStrictlyLower.h | 128 + .../math/typetraits/IsStrictlyTriangular.h | 94 + .../blaze/math/typetraits/IsStrictlyUpper.h | 128 + src/cpu/blaze/math/typetraits/IsSubExpr.h | 78 + src/cpu/blaze/math/typetraits/IsSubmatrix.h | 139 + src/cpu/blaze/math/typetraits/IsSubvector.h | 139 + src/cpu/blaze/math/typetraits/IsSymmetric.h | 127 + .../blaze/math/typetraits/IsTVecMatMultExpr.h | 80 + src/cpu/blaze/math/typetraits/IsTemporary.h | 77 + src/cpu/blaze/math/typetraits/IsTransExpr.h | 78 + src/cpu/blaze/math/typetraits/IsTriangular.h | 93 + src/cpu/blaze/math/typetraits/IsUniLower.h | 128 + .../blaze/math/typetraits/IsUniTriangular.h | 93 + src/cpu/blaze/math/typetraits/IsUniUpper.h | 128 + src/cpu/blaze/math/typetraits/IsUpper.h | 130 + src/cpu/blaze/math/typetraits/IsVecEvalExpr.h | 78 + .../blaze/math/typetraits/IsVecForEachExpr.h | 78 + .../math/typetraits/IsVecScalarDivExpr.h | 80 + .../math/typetraits/IsVecScalarMultExpr.h | 80 + .../blaze/math/typetraits/IsVecSerialExpr.h | 78 + .../blaze/math/typetraits/IsVecTVecMultExpr.h | 79 + .../blaze/math/typetraits/IsVecTransExpr.h | 78 + .../blaze/math/typetraits/IsVecVecAddExpr.h | 78 + .../blaze/math/typetraits/IsVecVecDivExpr.h | 79 + .../blaze/math/typetraits/IsVecVecMultExpr.h | 80 + .../blaze/math/typetraits/IsVecVecSubExpr.h | 80 + src/cpu/blaze/math/typetraits/IsVector.h | 86 + src/cpu/blaze/math/typetraits/IsView.h | 93 + src/cpu/blaze/math/typetraits/RemoveAdaptor.h | 158 + .../math/typetraits/RequiresEvaluation.h | 79 + src/cpu/blaze/math/typetraits/Rows.h | 118 + src/cpu/blaze/math/typetraits/Size.h | 117 + src/cpu/blaze/math/typetraits/StorageOrder.h | 83 + src/cpu/blaze/math/typetraits/TransposeFlag.h | 83 + src/cpu/blaze/math/typetraits/TypeTraits.h | 51 + .../blaze/math/typetraits/UnderlyingBuiltin.h | 138 + .../blaze/math/typetraits/UnderlyingElement.h | 138 + .../blaze/math/typetraits/UnderlyingNumeric.h | 130 + src/cpu/blaze/math/views/Column.h | 1074 ++ src/cpu/blaze/math/views/Forward.h | 54 + src/cpu/blaze/math/views/Row.h | 1072 ++ src/cpu/blaze/math/views/Submatrix.h | 2159 +++ src/cpu/blaze/math/views/Subvector.h | 1500 ++ src/cpu/blaze/math/views/Views.h | 51 + .../blaze/math/views/column/BaseTemplate.h | 360 + src/cpu/blaze/math/views/column/Dense.h | 5817 ++++++++ src/cpu/blaze/math/views/column/Sparse.h | 5360 ++++++++ src/cpu/blaze/math/views/row/BaseTemplate.h | 361 + src/cpu/blaze/math/views/row/Dense.h | 5800 ++++++++ src/cpu/blaze/math/views/row/Sparse.h | 5340 +++++++ .../blaze/math/views/submatrix/BaseTemplate.h | 509 + src/cpu/blaze/math/views/submatrix/Dense.h | 11127 +++++++++++++++ src/cpu/blaze/math/views/submatrix/Sparse.h | 4940 +++++++ .../blaze/math/views/subvector/BaseTemplate.h | 440 + src/cpu/blaze/math/views/subvector/Dense.h | 5270 +++++++ src/cpu/blaze/math/views/subvector/Sparse.h | 2004 +++ src/cpu/blaze/system/Assertion.h | 47 + src/cpu/blaze/system/BLAS.h | 62 + src/cpu/blaze/system/Blocking.h | 129 + src/cpu/blaze/system/CacheSize.h | 76 + src/cpu/blaze/system/Debugging.h | 64 + src/cpu/blaze/system/Deprecated.h | 68 + src/cpu/blaze/system/Inline.h | 89 + src/cpu/blaze/system/Logging.h | 56 + src/cpu/blaze/system/MPI.h | 47 + src/cpu/blaze/system/Optimizations.h | 47 + src/cpu/blaze/system/Precision.h | 75 + src/cpu/blaze/system/Random.h | 56 + src/cpu/blaze/system/Restrict.h | 85 + src/cpu/blaze/system/SMP.h | 126 + src/cpu/blaze/system/Signature.h | 72 + src/cpu/blaze/system/StorageOrder.h | 56 + src/cpu/blaze/system/System.h | 52 + src/cpu/blaze/system/Thresholds.h | 1034 ++ src/cpu/blaze/system/TransposeFlag.h | 56 + src/cpu/blaze/system/Vectorization.h | 349 + src/cpu/blaze/system/Version.h | 66 + src/cpu/blaze/system/WarningDisable.h | 79 + src/cpu/blaze/util/Algorithm.h | 150 + src/cpu/blaze/util/AlignedAllocator.h | 387 + src/cpu/blaze/util/AlignedArray.h | 501 + src/cpu/blaze/util/AlignmentCheck.h | 76 + src/cpu/blaze/util/Assert.h | 123 + src/cpu/blaze/util/ColorMacros.h | 166 + src/cpu/blaze/util/Complex.h | 64 + src/cpu/blaze/util/Constraints.h | 85 + src/cpu/blaze/util/Convert.h | 654 + src/cpu/blaze/util/DimensionOf.h | 101 + src/cpu/blaze/util/DisableIf.h | 228 + src/cpu/blaze/util/EmptyType.h | 51 + src/cpu/blaze/util/EnableIf.h | 228 + src/cpu/blaze/util/Exception.h | 383 + src/cpu/blaze/util/FalseType.h | 66 + src/cpu/blaze/util/Indices.h | 220 + src/cpu/blaze/util/InputString.h | 434 + src/cpu/blaze/util/IntegralConstant.h | 105 + src/cpu/blaze/util/InvalidType.h | 59 + src/cpu/blaze/util/Limits.h | 440 + src/cpu/blaze/util/Logging.h | 51 + src/cpu/blaze/util/MPL.h | 64 + src/cpu/blaze/util/Memory.h | 278 + src/cpu/blaze/util/MemoryPool.h | 300 + src/cpu/blaze/util/Misalignment.h | 76 + src/cpu/blaze/util/NonCopyable.h | 86 + src/cpu/blaze/util/NonCreatable.h | 81 + src/cpu/blaze/util/NullType.h | 60 + src/cpu/blaze/util/PointerCast.h | 286 + src/cpu/blaze/util/Policies.h | 52 + src/cpu/blaze/util/PtrIterator.h | 563 + src/cpu/blaze/util/PtrVector.h | 2615 ++++ src/cpu/blaze/util/Random.h | 1000 ++ src/cpu/blaze/util/Serialization.h | 45 + src/cpu/blaze/util/Singleton.h | 46 + src/cpu/blaze/util/StaticAssert.h | 129 + src/cpu/blaze/util/Suffix.h | 55 + src/cpu/blaze/util/SystemClock.h | 194 + src/cpu/blaze/util/SystemClockID.h | 82 + src/cpu/blaze/util/Template.h | 80 + src/cpu/blaze/util/Thread.h | 498 + src/cpu/blaze/util/ThreadPool.h | 801 ++ src/cpu/blaze/util/Time.h | 171 + src/cpu/blaze/util/Timing.h | 49 + src/cpu/blaze/util/TrueType.h | 66 + src/cpu/blaze/util/TypeList.h | 1071 ++ src/cpu/blaze/util/TypeTraits.h | 106 + src/cpu/blaze/util/Types.h | 180 + src/cpu/blaze/util/UnsignedValue.h | 391 + src/cpu/blaze/util/Unused.h | 157 + src/cpu/blaze/util/Util.h | 49 + src/cpu/blaze/util/ValueTraits.h | 48 + src/cpu/blaze/util/constraints/Arithmetic.h | 86 + src/cpu/blaze/util/constraints/Array.h | 85 + src/cpu/blaze/util/constraints/Assignable.h | 207 + src/cpu/blaze/util/constraints/BaseOf.h | 128 + src/cpu/blaze/util/constraints/Boolean.h | 85 + src/cpu/blaze/util/constraints/Builtin.h | 85 + src/cpu/blaze/util/constraints/Class.h | 87 + src/cpu/blaze/util/constraints/Comparable.h | 66 + src/cpu/blaze/util/constraints/Complex.h | 89 + .../blaze/util/constraints/ComplexDouble.h | 89 + src/cpu/blaze/util/constraints/ComplexFloat.h | 89 + src/cpu/blaze/util/constraints/Const.h | 85 + src/cpu/blaze/util/constraints/Constraints.h | 115 + .../blaze/util/constraints/Constructible.h | 287 + src/cpu/blaze/util/constraints/Convertible.h | 85 + src/cpu/blaze/util/constraints/DerivedFrom.h | 128 + src/cpu/blaze/util/constraints/Destructible.h | 127 + src/cpu/blaze/util/constraints/Double.h | 89 + src/cpu/blaze/util/constraints/Empty.h | 85 + src/cpu/blaze/util/constraints/Float.h | 89 + .../blaze/util/constraints/FloatingPoint.h | 87 + src/cpu/blaze/util/constraints/Integer.h | 88 + src/cpu/blaze/util/constraints/Integral.h | 85 + src/cpu/blaze/util/constraints/LongDouble.h | 89 + src/cpu/blaze/util/constraints/Numeric.h | 87 + src/cpu/blaze/util/constraints/Object.h | 86 + src/cpu/blaze/util/constraints/Pod.h | 85 + src/cpu/blaze/util/constraints/Pointer.h | 85 + src/cpu/blaze/util/constraints/Rank.h | 85 + src/cpu/blaze/util/constraints/Reference.h | 85 + src/cpu/blaze/util/constraints/SameSize.h | 85 + src/cpu/blaze/util/constraints/SameType.h | 166 + src/cpu/blaze/util/constraints/Signed.h | 87 + src/cpu/blaze/util/constraints/Size.h | 238 + .../blaze/util/constraints/Subscriptable.h | 85 + .../blaze/util/constraints/TypeRestriction.h | 87 + src/cpu/blaze/util/constraints/Union.h | 85 + src/cpu/blaze/util/constraints/Unsigned.h | 87 + src/cpu/blaze/util/constraints/Valid.h | 85 + src/cpu/blaze/util/constraints/Vectorizable.h | 87 + src/cpu/blaze/util/constraints/Void.h | 85 + src/cpu/blaze/util/constraints/Volatile.h | 85 + src/cpu/blaze/util/logging/DebugSection.h | 105 + src/cpu/blaze/util/logging/DetailSection.h | 105 + src/cpu/blaze/util/logging/ErrorSection.h | 105 + src/cpu/blaze/util/logging/FunctionTrace.h | 165 + src/cpu/blaze/util/logging/InfoSection.h | 105 + src/cpu/blaze/util/logging/LogLevel.h | 91 + src/cpu/blaze/util/logging/LogSection.h | 230 + src/cpu/blaze/util/logging/Logger.h | 161 + src/cpu/blaze/util/logging/Logging.h | 224 + src/cpu/blaze/util/logging/ProgressSection.h | 105 + src/cpu/blaze/util/logging/WarningSection.h | 105 + src/cpu/blaze/util/mpl/And.h | 108 + src/cpu/blaze/util/mpl/Bool.h | 76 + src/cpu/blaze/util/mpl/Char.h | 76 + src/cpu/blaze/util/mpl/Equal.h | 79 + src/cpu/blaze/util/mpl/Greater.h | 80 + src/cpu/blaze/util/mpl/If.h | 165 + src/cpu/blaze/util/mpl/Int.h | 76 + src/cpu/blaze/util/mpl/Less.h | 84 + src/cpu/blaze/util/mpl/Long.h | 76 + src/cpu/blaze/util/mpl/MPL.h | 51 + src/cpu/blaze/util/mpl/Max.h | 78 + src/cpu/blaze/util/mpl/Min.h | 78 + src/cpu/blaze/util/mpl/Minus.h | 80 + src/cpu/blaze/util/mpl/Modulus.h | 81 + src/cpu/blaze/util/mpl/NextMultiple.h | 93 + src/cpu/blaze/util/mpl/Not.h | 76 + src/cpu/blaze/util/mpl/Or.h | 108 + src/cpu/blaze/util/mpl/Plus.h | 80 + src/cpu/blaze/util/mpl/SizeT.h | 78 + src/cpu/blaze/util/mpl/Times.h | 80 + src/cpu/blaze/util/mpl/Xor.h | 80 + src/cpu/blaze/util/policies/ArrayDelete.h | 104 + src/cpu/blaze/util/policies/ConstantGrowth.h | 112 + src/cpu/blaze/util/policies/Deallocate.h | 105 + src/cpu/blaze/util/policies/DefaultDelete.h | 158 + src/cpu/blaze/util/policies/LinearGrowth.h | 122 + src/cpu/blaze/util/policies/NoDelete.h | 85 + src/cpu/blaze/util/policies/OptimalGrowth.h | 101 + src/cpu/blaze/util/policies/PtrDelete.h | 104 + src/cpu/blaze/util/serialization/Archive.h | 537 + .../blaze/util/serialization/Serialization.h | 51 + src/cpu/blaze/util/singleton/Dependency.h | 135 + src/cpu/blaze/util/singleton/Singleton.h | 1341 ++ src/cpu/blaze/util/threadpool/Task.h | 67 + src/cpu/blaze/util/threadpool/TaskQueue.h | 315 + src/cpu/blaze/util/threadpool/ThreadPool.h | 54 + src/cpu/blaze/util/timing/CpuPolicy.h | 100 + src/cpu/blaze/util/timing/CpuTimer.h | 72 + src/cpu/blaze/util/timing/Timer.h | 370 + src/cpu/blaze/util/timing/Timing.h | 108 + src/cpu/blaze/util/timing/WcPolicy.h | 100 + src/cpu/blaze/util/timing/WcTimer.h | 73 + src/cpu/blaze/util/typetraits/AddCV.h | 101 + src/cpu/blaze/util/typetraits/AddConst.h | 100 + src/cpu/blaze/util/typetraits/AddPointer.h | 100 + src/cpu/blaze/util/typetraits/AddReference.h | 100 + src/cpu/blaze/util/typetraits/AddVolatile.h | 100 + src/cpu/blaze/util/typetraits/AlignmentOf.h | 249 + src/cpu/blaze/util/typetraits/All.h | 86 + src/cpu/blaze/util/typetraits/Any.h | 86 + src/cpu/blaze/util/typetraits/CommonType.h | 100 + src/cpu/blaze/util/typetraits/Decay.h | 103 + src/cpu/blaze/util/typetraits/Extent.h | 127 + src/cpu/blaze/util/typetraits/GetMemberType.h | 116 + src/cpu/blaze/util/typetraits/HasMember.h | 284 + src/cpu/blaze/util/typetraits/HasSize.h | 285 + src/cpu/blaze/util/typetraits/HaveSameSize.h | 150 + src/cpu/blaze/util/typetraits/IsArithmetic.h | 84 + src/cpu/blaze/util/typetraits/IsArray.h | 81 + src/cpu/blaze/util/typetraits/IsAssignable.h | 191 + src/cpu/blaze/util/typetraits/IsBaseOf.h | 86 + src/cpu/blaze/util/typetraits/IsBoolean.h | 121 + src/cpu/blaze/util/typetraits/IsBuiltin.h | 81 + src/cpu/blaze/util/typetraits/IsCharacter.h | 152 + src/cpu/blaze/util/typetraits/IsClass.h | 83 + src/cpu/blaze/util/typetraits/IsComplex.h | 122 + .../blaze/util/typetraits/IsComplexDouble.h | 122 + .../blaze/util/typetraits/IsComplexFloat.h | 122 + src/cpu/blaze/util/typetraits/IsConst.h | 81 + .../blaze/util/typetraits/IsConstructible.h | 232 + src/cpu/blaze/util/typetraits/IsConvertible.h | 93 + .../blaze/util/typetraits/IsDestructible.h | 102 + src/cpu/blaze/util/typetraits/IsDouble.h | 121 + src/cpu/blaze/util/typetraits/IsEmpty.h | 84 + src/cpu/blaze/util/typetraits/IsFloat.h | 121 + .../blaze/util/typetraits/IsFloatingPoint.h | 81 + src/cpu/blaze/util/typetraits/IsInteger.h | 166 + src/cpu/blaze/util/typetraits/IsIntegral.h | 81 + src/cpu/blaze/util/typetraits/IsLong.h | 162 + src/cpu/blaze/util/typetraits/IsLongDouble.h | 121 + src/cpu/blaze/util/typetraits/IsNumeric.h | 125 + src/cpu/blaze/util/typetraits/IsObject.h | 82 + src/cpu/blaze/util/typetraits/IsPod.h | 93 + src/cpu/blaze/util/typetraits/IsPointer.h | 81 + src/cpu/blaze/util/typetraits/IsReference.h | 81 + src/cpu/blaze/util/typetraits/IsSame.h | 144 + src/cpu/blaze/util/typetraits/IsShort.h | 162 + src/cpu/blaze/util/typetraits/IsSigned.h | 83 + src/cpu/blaze/util/typetraits/IsUnion.h | 84 + src/cpu/blaze/util/typetraits/IsUnsigned.h | 83 + src/cpu/blaze/util/typetraits/IsValid.h | 122 + .../blaze/util/typetraits/IsVectorizable.h | 139 + src/cpu/blaze/util/typetraits/IsVoid.h | 81 + src/cpu/blaze/util/typetraits/IsVolatile.h | 81 + src/cpu/blaze/util/typetraits/MakeSigned.h | 104 + src/cpu/blaze/util/typetraits/MakeUnsigned.h | 104 + src/cpu/blaze/util/typetraits/Rank.h | 98 + .../blaze/util/typetraits/RemoveAllExtents.h | 101 + src/cpu/blaze/util/typetraits/RemoveCV.h | 102 + src/cpu/blaze/util/typetraits/RemoveConst.h | 101 + src/cpu/blaze/util/typetraits/RemoveExtent.h | 100 + src/cpu/blaze/util/typetraits/RemovePointer.h | 100 + .../blaze/util/typetraits/RemoveReference.h | 100 + .../blaze/util/typetraits/RemoveVolatile.h | 102 + src/cpu/blaze/util/typetraits/TypeTraits.h | 51 + src/cpu/blaze/util/valuetraits/IsEven.h | 79 + src/cpu/blaze/util/valuetraits/IsMultipleOf.h | 109 + src/cpu/blaze/util/valuetraits/IsOdd.h | 79 + src/cpu/blaze/util/valuetraits/IsPowerOf.h | 221 + src/cpu/blaze/util/valuetraits/ValueTraits.h | 51 + src/cpu/dl4mt/decoder.h | 287 + src/cpu/dl4mt/dl4mt.h | 5 + src/cpu/dl4mt/encoder.cpp | 24 + src/cpu/dl4mt/encoder.h | 93 + src/cpu/dl4mt/gru.h | 76 + src/cpu/dl4mt/model.cpp | 74 + src/cpu/dl4mt/model.h | 184 + src/cpu/mblas/matrix.cpp | 40 + src/cpu/mblas/matrix.h | 269 + src/cpu/mblas/phoenix_functions.cpp | 9 + src/cpu/mblas/phoenix_functions.h | 107 + src/cpu/mblas/simd_math_prims.h | 117 + src/cpu/npz_converter.h | 88 + 1235 files changed, 553444 insertions(+), 4 deletions(-) create mode 100644 src/cpu/blaze/Blaze.h create mode 100644 src/cpu/blaze/Math.h create mode 100644 src/cpu/blaze/Tutorial.h create mode 100644 src/cpu/blaze/Util.h create mode 100644 src/cpu/blaze/config/Assertion.h create mode 100644 src/cpu/blaze/config/BLAS.h create mode 100644 src/cpu/blaze/config/CacheSize.h create mode 100644 src/cpu/blaze/config/Config.h create mode 100644 src/cpu/blaze/config/Debugging.h create mode 100644 src/cpu/blaze/config/Inline.h create mode 100644 src/cpu/blaze/config/Logging.h create mode 100644 src/cpu/blaze/config/MPI.h create mode 100644 src/cpu/blaze/config/Optimizations.h create mode 100644 src/cpu/blaze/config/Precision.h create mode 100644 src/cpu/blaze/config/Random.h create mode 100644 src/cpu/blaze/config/Restrict.h create mode 100644 src/cpu/blaze/config/SMP.h create mode 100644 src/cpu/blaze/config/StorageOrder.h create mode 100644 src/cpu/blaze/config/Thresholds.h create mode 100644 src/cpu/blaze/config/TransposeFlag.h create mode 100644 src/cpu/blaze/config/Vectorization.h create mode 100644 src/cpu/blaze/math/Accuracy.h create mode 100644 src/cpu/blaze/math/Aliases.h create mode 100644 src/cpu/blaze/math/AlignmentFlag.h create mode 100644 src/cpu/blaze/math/BLAS.h create mode 100644 src/cpu/blaze/math/Column.h create mode 100644 src/cpu/blaze/math/CompressedMatrix.h create mode 100644 src/cpu/blaze/math/CompressedVector.h create mode 100644 src/cpu/blaze/math/Constants.h create mode 100644 src/cpu/blaze/math/Constraints.h create mode 100644 src/cpu/blaze/math/CustomMatrix.h create mode 100644 src/cpu/blaze/math/CustomVector.h create mode 100644 src/cpu/blaze/math/DenseMatrix.h create mode 100644 src/cpu/blaze/math/DenseVector.h create mode 100644 src/cpu/blaze/math/DiagonalMatrix.h create mode 100644 src/cpu/blaze/math/DynamicMatrix.h create mode 100644 src/cpu/blaze/math/DynamicVector.h create mode 100644 src/cpu/blaze/math/Epsilon.h create mode 100644 src/cpu/blaze/math/Exception.h create mode 100644 src/cpu/blaze/math/Forward.h create mode 100644 src/cpu/blaze/math/Functions.h create mode 100644 src/cpu/blaze/math/Functors.h create mode 100644 src/cpu/blaze/math/HermitianMatrix.h create mode 100644 src/cpu/blaze/math/HybridMatrix.h create mode 100644 src/cpu/blaze/math/HybridVector.h create mode 100644 src/cpu/blaze/math/Infinity.h create mode 100644 src/cpu/blaze/math/InitializerList.h create mode 100644 src/cpu/blaze/math/InversionFlag.h create mode 100644 src/cpu/blaze/math/LAPACK.h create mode 100644 src/cpu/blaze/math/LowerMatrix.h create mode 100644 src/cpu/blaze/math/Math.h create mode 100644 src/cpu/blaze/math/Matrix.h create mode 100644 src/cpu/blaze/math/PaddingFlag.h create mode 100644 src/cpu/blaze/math/Row.h create mode 100644 src/cpu/blaze/math/SIMD.h create mode 100644 src/cpu/blaze/math/SMP.h create mode 100644 src/cpu/blaze/math/Serialization.h create mode 100644 src/cpu/blaze/math/Shims.h create mode 100644 src/cpu/blaze/math/SparseMatrix.h create mode 100644 src/cpu/blaze/math/SparseVector.h create mode 100644 src/cpu/blaze/math/StaticMatrix.h create mode 100644 src/cpu/blaze/math/StaticVector.h create mode 100644 src/cpu/blaze/math/StorageOrder.h create mode 100644 src/cpu/blaze/math/StrictlyLowerMatrix.h create mode 100644 src/cpu/blaze/math/StrictlyUpperMatrix.h create mode 100644 src/cpu/blaze/math/Submatrix.h create mode 100644 src/cpu/blaze/math/Subvector.h create mode 100644 src/cpu/blaze/math/SymmetricMatrix.h create mode 100644 src/cpu/blaze/math/Traits.h create mode 100644 src/cpu/blaze/math/TransposeFlag.h create mode 100644 src/cpu/blaze/math/TypeTraits.h create mode 100644 src/cpu/blaze/math/UniLowerMatrix.h create mode 100644 src/cpu/blaze/math/UniUpperMatrix.h create mode 100644 src/cpu/blaze/math/UpperMatrix.h create mode 100644 src/cpu/blaze/math/Vector.h create mode 100644 src/cpu/blaze/math/Views.h create mode 100644 src/cpu/blaze/math/adaptors/Adaptors.h create mode 100644 src/cpu/blaze/math/adaptors/DiagonalMatrix.h create mode 100644 src/cpu/blaze/math/adaptors/Forward.h create mode 100644 src/cpu/blaze/math/adaptors/HermitianMatrix.h create mode 100644 src/cpu/blaze/math/adaptors/LowerMatrix.h create mode 100644 src/cpu/blaze/math/adaptors/StrictlyLowerMatrix.h create mode 100644 src/cpu/blaze/math/adaptors/StrictlyUpperMatrix.h create mode 100644 src/cpu/blaze/math/adaptors/SymmetricMatrix.h create mode 100644 src/cpu/blaze/math/adaptors/UniLowerMatrix.h create mode 100644 src/cpu/blaze/math/adaptors/UniUpperMatrix.h create mode 100644 src/cpu/blaze/math/adaptors/UpperMatrix.h create mode 100644 src/cpu/blaze/math/adaptors/diagonalmatrix/BaseTemplate.h create mode 100644 src/cpu/blaze/math/adaptors/diagonalmatrix/Dense.h create mode 100644 src/cpu/blaze/math/adaptors/diagonalmatrix/DiagonalProxy.h create mode 100644 src/cpu/blaze/math/adaptors/diagonalmatrix/Sparse.h create mode 100644 src/cpu/blaze/math/adaptors/hermitianmatrix/BaseTemplate.h create mode 100644 src/cpu/blaze/math/adaptors/hermitianmatrix/Dense.h create mode 100644 src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianElement.h create mode 100644 src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianProxy.h create mode 100644 src/cpu/blaze/math/adaptors/hermitianmatrix/HermitianValue.h create mode 100644 src/cpu/blaze/math/adaptors/hermitianmatrix/Sparse.h create mode 100644 src/cpu/blaze/math/adaptors/lowermatrix/BaseTemplate.h create mode 100644 src/cpu/blaze/math/adaptors/lowermatrix/Dense.h create mode 100644 src/cpu/blaze/math/adaptors/lowermatrix/LowerProxy.h create mode 100644 src/cpu/blaze/math/adaptors/lowermatrix/Sparse.h create mode 100644 src/cpu/blaze/math/adaptors/strictlylowermatrix/BaseTemplate.h create mode 100644 src/cpu/blaze/math/adaptors/strictlylowermatrix/Dense.h create mode 100644 src/cpu/blaze/math/adaptors/strictlylowermatrix/Sparse.h create mode 100644 src/cpu/blaze/math/adaptors/strictlylowermatrix/StrictlyLowerProxy.h create mode 100644 src/cpu/blaze/math/adaptors/strictlyuppermatrix/BaseTemplate.h create mode 100644 src/cpu/blaze/math/adaptors/strictlyuppermatrix/Dense.h create mode 100644 src/cpu/blaze/math/adaptors/strictlyuppermatrix/Sparse.h create mode 100644 src/cpu/blaze/math/adaptors/strictlyuppermatrix/StrictlyUpperProxy.h create mode 100644 src/cpu/blaze/math/adaptors/symmetricmatrix/BaseTemplate.h create mode 100644 src/cpu/blaze/math/adaptors/symmetricmatrix/DenseNonNumeric.h create mode 100644 src/cpu/blaze/math/adaptors/symmetricmatrix/DenseNumeric.h create mode 100644 src/cpu/blaze/math/adaptors/symmetricmatrix/NonNumericProxy.h create mode 100644 src/cpu/blaze/math/adaptors/symmetricmatrix/NumericProxy.h create mode 100644 src/cpu/blaze/math/adaptors/symmetricmatrix/SharedValue.h create mode 100644 src/cpu/blaze/math/adaptors/symmetricmatrix/SparseNonNumeric.h create mode 100644 src/cpu/blaze/math/adaptors/symmetricmatrix/SparseNumeric.h create mode 100644 src/cpu/blaze/math/adaptors/symmetricmatrix/SymmetricElement.h create mode 100644 src/cpu/blaze/math/adaptors/symmetricmatrix/SymmetricValue.h create mode 100644 src/cpu/blaze/math/adaptors/unilowermatrix/BaseTemplate.h create mode 100644 src/cpu/blaze/math/adaptors/unilowermatrix/Dense.h create mode 100644 src/cpu/blaze/math/adaptors/unilowermatrix/Sparse.h create mode 100644 src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerElement.h create mode 100644 src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerProxy.h create mode 100644 src/cpu/blaze/math/adaptors/unilowermatrix/UniLowerValue.h create mode 100644 src/cpu/blaze/math/adaptors/uniuppermatrix/BaseTemplate.h create mode 100644 src/cpu/blaze/math/adaptors/uniuppermatrix/Dense.h create mode 100644 src/cpu/blaze/math/adaptors/uniuppermatrix/Sparse.h create mode 100644 src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperElement.h create mode 100644 src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperProxy.h create mode 100644 src/cpu/blaze/math/adaptors/uniuppermatrix/UniUpperValue.h create mode 100644 src/cpu/blaze/math/adaptors/uppermatrix/BaseTemplate.h create mode 100644 src/cpu/blaze/math/adaptors/uppermatrix/Dense.h create mode 100644 src/cpu/blaze/math/adaptors/uppermatrix/Sparse.h create mode 100644 src/cpu/blaze/math/adaptors/uppermatrix/UpperProxy.h create mode 100644 src/cpu/blaze/math/blas/BLAS.h create mode 100644 src/cpu/blaze/math/blas/dot.h create mode 100644 src/cpu/blaze/math/blas/gemm.h create mode 100644 src/cpu/blaze/math/blas/gemv.h create mode 100644 src/cpu/blaze/math/blas/trmm.h create mode 100644 src/cpu/blaze/math/blas/trmv.h create mode 100644 src/cpu/blaze/math/blas/trsm.h create mode 100644 src/cpu/blaze/math/constraints/Adaptor.h create mode 100644 src/cpu/blaze/math/constraints/AddExpr.h create mode 100644 src/cpu/blaze/math/constraints/Aligned.h create mode 100644 src/cpu/blaze/math/constraints/BLASCompatible.h create mode 100644 src/cpu/blaze/math/constraints/Column.h create mode 100644 src/cpu/blaze/math/constraints/ColumnMajorMatrix.h create mode 100644 src/cpu/blaze/math/constraints/ColumnVector.h create mode 100644 src/cpu/blaze/math/constraints/Columns.h create mode 100644 src/cpu/blaze/math/constraints/Computation.h create mode 100644 src/cpu/blaze/math/constraints/ConstDataAccess.h create mode 100644 src/cpu/blaze/math/constraints/Constraints.h create mode 100644 src/cpu/blaze/math/constraints/CrossExpr.h create mode 100644 src/cpu/blaze/math/constraints/Custom.h create mode 100644 src/cpu/blaze/math/constraints/DenseMatrix.h create mode 100644 src/cpu/blaze/math/constraints/DenseVector.h create mode 100644 src/cpu/blaze/math/constraints/Diagonal.h create mode 100644 src/cpu/blaze/math/constraints/DivExpr.h create mode 100644 src/cpu/blaze/math/constraints/EvalExpr.h create mode 100644 src/cpu/blaze/math/constraints/Expression.h create mode 100644 src/cpu/blaze/math/constraints/ForEachExpr.h create mode 100644 src/cpu/blaze/math/constraints/General.h create mode 100644 src/cpu/blaze/math/constraints/Hermitian.h create mode 100644 src/cpu/blaze/math/constraints/Identity.h create mode 100644 src/cpu/blaze/math/constraints/Invertible.h create mode 100644 src/cpu/blaze/math/constraints/Lower.h create mode 100644 src/cpu/blaze/math/constraints/MatEvalExpr.h create mode 100644 src/cpu/blaze/math/constraints/MatForEachExpr.h create mode 100644 src/cpu/blaze/math/constraints/MatInvExpr.h create mode 100644 src/cpu/blaze/math/constraints/MatMatAddExpr.h create mode 100644 src/cpu/blaze/math/constraints/MatMatMultExpr.h create mode 100644 src/cpu/blaze/math/constraints/MatMatSubExpr.h create mode 100644 src/cpu/blaze/math/constraints/MatScalarDivExpr.h create mode 100644 src/cpu/blaze/math/constraints/MatScalarMultExpr.h create mode 100644 src/cpu/blaze/math/constraints/MatSerialExpr.h create mode 100644 src/cpu/blaze/math/constraints/MatTransExpr.h create mode 100644 src/cpu/blaze/math/constraints/MatVecMultExpr.h create mode 100644 src/cpu/blaze/math/constraints/Matrix.h create mode 100644 src/cpu/blaze/math/constraints/MultExpr.h create mode 100644 src/cpu/blaze/math/constraints/MutableDataAccess.h create mode 100644 src/cpu/blaze/math/constraints/NumericMatrix.h create mode 100644 src/cpu/blaze/math/constraints/NumericVector.h create mode 100644 src/cpu/blaze/math/constraints/OpposedView.h create mode 100644 src/cpu/blaze/math/constraints/Padded.h create mode 100644 src/cpu/blaze/math/constraints/Proxy.h create mode 100644 src/cpu/blaze/math/constraints/RequiresEvaluation.h create mode 100644 src/cpu/blaze/math/constraints/Resizable.h create mode 100644 src/cpu/blaze/math/constraints/Restricted.h create mode 100644 src/cpu/blaze/math/constraints/Row.h create mode 100644 src/cpu/blaze/math/constraints/RowMajorMatrix.h create mode 100644 src/cpu/blaze/math/constraints/RowVector.h create mode 100644 src/cpu/blaze/math/constraints/Rows.h create mode 100644 src/cpu/blaze/math/constraints/SIMDEnabled.h create mode 100644 src/cpu/blaze/math/constraints/SIMDPack.h create mode 100644 src/cpu/blaze/math/constraints/SMPAssignable.h create mode 100644 src/cpu/blaze/math/constraints/SerialExpr.h create mode 100644 src/cpu/blaze/math/constraints/Size.h create mode 100644 src/cpu/blaze/math/constraints/SparseElement.h create mode 100644 src/cpu/blaze/math/constraints/SparseMatrix.h create mode 100644 src/cpu/blaze/math/constraints/SparseVector.h create mode 100644 src/cpu/blaze/math/constraints/Square.h create mode 100644 src/cpu/blaze/math/constraints/StorageOrder.h create mode 100644 src/cpu/blaze/math/constraints/StrictlyLower.h create mode 100644 src/cpu/blaze/math/constraints/StrictlyTriangular.h create mode 100644 src/cpu/blaze/math/constraints/StrictlyUpper.h create mode 100644 src/cpu/blaze/math/constraints/SubExpr.h create mode 100644 src/cpu/blaze/math/constraints/Submatrix.h create mode 100644 src/cpu/blaze/math/constraints/Subvector.h create mode 100644 src/cpu/blaze/math/constraints/Symmetric.h create mode 100644 src/cpu/blaze/math/constraints/TVecMatMultExpr.h create mode 100644 src/cpu/blaze/math/constraints/TransExpr.h create mode 100644 src/cpu/blaze/math/constraints/TransposeFlag.h create mode 100644 src/cpu/blaze/math/constraints/Triangular.h create mode 100644 src/cpu/blaze/math/constraints/UniLower.h create mode 100644 src/cpu/blaze/math/constraints/UniTriangular.h create mode 100644 src/cpu/blaze/math/constraints/UniUpper.h create mode 100644 src/cpu/blaze/math/constraints/Upper.h create mode 100644 src/cpu/blaze/math/constraints/VecEvalExpr.h create mode 100644 src/cpu/blaze/math/constraints/VecForEachExpr.h create mode 100644 src/cpu/blaze/math/constraints/VecScalarDivExpr.h create mode 100644 src/cpu/blaze/math/constraints/VecScalarMultExpr.h create mode 100644 src/cpu/blaze/math/constraints/VecSerialExpr.h create mode 100644 src/cpu/blaze/math/constraints/VecTVecMultExpr.h create mode 100644 src/cpu/blaze/math/constraints/VecTransExpr.h create mode 100644 src/cpu/blaze/math/constraints/VecVecAddExpr.h create mode 100644 src/cpu/blaze/math/constraints/VecVecDivExpr.h create mode 100644 src/cpu/blaze/math/constraints/VecVecMultExpr.h create mode 100644 src/cpu/blaze/math/constraints/VecVecSubExpr.h create mode 100644 src/cpu/blaze/math/constraints/Vector.h create mode 100644 src/cpu/blaze/math/constraints/View.h create mode 100644 src/cpu/blaze/math/dense/CustomMatrix.h create mode 100644 src/cpu/blaze/math/dense/CustomVector.h create mode 100644 src/cpu/blaze/math/dense/DenseIterator.h create mode 100644 src/cpu/blaze/math/dense/DenseMatrix.h create mode 100644 src/cpu/blaze/math/dense/DenseVector.h create mode 100644 src/cpu/blaze/math/dense/DynamicMatrix.h create mode 100644 src/cpu/blaze/math/dense/DynamicVector.h create mode 100644 src/cpu/blaze/math/dense/Forward.h create mode 100644 src/cpu/blaze/math/dense/HybridMatrix.h create mode 100644 src/cpu/blaze/math/dense/HybridVector.h create mode 100644 src/cpu/blaze/math/dense/Inversion.h create mode 100644 src/cpu/blaze/math/dense/LLH.h create mode 100644 src/cpu/blaze/math/dense/LQ.h create mode 100644 src/cpu/blaze/math/dense/LU.h create mode 100644 src/cpu/blaze/math/dense/QL.h create mode 100644 src/cpu/blaze/math/dense/QR.h create mode 100644 src/cpu/blaze/math/dense/RQ.h create mode 100644 src/cpu/blaze/math/dense/StaticMatrix.h create mode 100644 src/cpu/blaze/math/dense/StaticVector.h create mode 100644 src/cpu/blaze/math/expressions/AddExpr.h create mode 100644 src/cpu/blaze/math/expressions/Computation.h create mode 100644 src/cpu/blaze/math/expressions/CrossExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatDMatAddExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatDMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatDMatSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatDVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatDetExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatEvalExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatForEachExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatInvExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatSMatAddExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatSMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatSMatSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatSVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatScalarDivExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatScalarMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatSerialExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatTDMatAddExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatTDMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatTDMatSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatTSMatAddExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatTSMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatTSMatSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatTransExpr.h create mode 100644 src/cpu/blaze/math/expressions/DMatTransposer.h create mode 100644 src/cpu/blaze/math/expressions/DVecDVecAddExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecDVecCrossExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecDVecDivExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecDVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecDVecSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecEvalExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecForEachExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecSVecAddExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecSVecCrossExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecSVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecSVecSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecScalarDivExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecScalarMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecSerialExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecTDVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecTSVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecTransExpr.h create mode 100644 src/cpu/blaze/math/expressions/DVecTransposer.h create mode 100644 src/cpu/blaze/math/expressions/DenseMatrix.h create mode 100644 src/cpu/blaze/math/expressions/DenseVector.h create mode 100644 src/cpu/blaze/math/expressions/DivExpr.h create mode 100644 src/cpu/blaze/math/expressions/EvalExpr.h create mode 100644 src/cpu/blaze/math/expressions/Expression.h create mode 100644 src/cpu/blaze/math/expressions/ForEachExpr.h create mode 100644 src/cpu/blaze/math/expressions/Forward.h create mode 100644 src/cpu/blaze/math/expressions/MatEvalExpr.h create mode 100644 src/cpu/blaze/math/expressions/MatForEachExpr.h create mode 100644 src/cpu/blaze/math/expressions/MatInvExpr.h create mode 100644 src/cpu/blaze/math/expressions/MatMatAddExpr.h create mode 100644 src/cpu/blaze/math/expressions/MatMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/MatMatSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/MatScalarDivExpr.h create mode 100644 src/cpu/blaze/math/expressions/MatScalarMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/MatSerialExpr.h create mode 100644 src/cpu/blaze/math/expressions/MatTransExpr.h create mode 100644 src/cpu/blaze/math/expressions/MatVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/Matrix.h create mode 100644 src/cpu/blaze/math/expressions/MultExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatDMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatDMatSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatDVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatEvalExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatForEachExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatSMatAddExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatSMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatSMatSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatSVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatScalarDivExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatScalarMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatSerialExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatTDMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatTDMatSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatTSMatAddExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatTSMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatTSMatSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatTransExpr.h create mode 100644 src/cpu/blaze/math/expressions/SMatTransposer.h create mode 100644 src/cpu/blaze/math/expressions/SVecDVecCrossExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecDVecDivExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecDVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecDVecSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecEvalExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecForEachExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecSVecAddExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecSVecCrossExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecSVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecSVecSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecScalarDivExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecScalarMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecSerialExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecTDVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecTSVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecTransExpr.h create mode 100644 src/cpu/blaze/math/expressions/SVecTransposer.h create mode 100644 src/cpu/blaze/math/expressions/SerialExpr.h create mode 100644 src/cpu/blaze/math/expressions/SparseMatrix.h create mode 100644 src/cpu/blaze/math/expressions/SparseVector.h create mode 100644 src/cpu/blaze/math/expressions/SubExpr.h create mode 100644 src/cpu/blaze/math/expressions/TDMatDMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TDMatDVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TDMatSMatAddExpr.h create mode 100644 src/cpu/blaze/math/expressions/TDMatSMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TDMatSMatSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/TDMatSVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TDMatTDMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TDMatTSMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TDVecDMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TDVecDVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TDVecSMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TDVecSVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TDVecTDMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TDVecTSMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSMatDMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSMatDMatSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSMatDVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSMatSMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSMatSMatSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSMatSVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSMatTDMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSMatTSMatAddExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSMatTSMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSMatTSMatSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSVecDMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSVecDVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSVecSMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSVecSVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSVecTDMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TSVecTSMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TVecMatMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/TransExpr.h create mode 100644 src/cpu/blaze/math/expressions/VecEvalExpr.h create mode 100644 src/cpu/blaze/math/expressions/VecForEachExpr.h create mode 100644 src/cpu/blaze/math/expressions/VecScalarDivExpr.h create mode 100644 src/cpu/blaze/math/expressions/VecScalarMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/VecSerialExpr.h create mode 100644 src/cpu/blaze/math/expressions/VecTVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/VecTransExpr.h create mode 100644 src/cpu/blaze/math/expressions/VecVecAddExpr.h create mode 100644 src/cpu/blaze/math/expressions/VecVecDivExpr.h create mode 100644 src/cpu/blaze/math/expressions/VecVecMultExpr.h create mode 100644 src/cpu/blaze/math/expressions/VecVecSubExpr.h create mode 100644 src/cpu/blaze/math/expressions/Vector.h create mode 100644 src/cpu/blaze/math/expressions/View.h create mode 100644 src/cpu/blaze/math/functors/Abs.h create mode 100644 src/cpu/blaze/math/functors/Acos.h create mode 100644 src/cpu/blaze/math/functors/Acosh.h create mode 100644 src/cpu/blaze/math/functors/Asin.h create mode 100644 src/cpu/blaze/math/functors/Asinh.h create mode 100644 src/cpu/blaze/math/functors/Atan.h create mode 100644 src/cpu/blaze/math/functors/Atanh.h create mode 100644 src/cpu/blaze/math/functors/CTrans.h create mode 100644 src/cpu/blaze/math/functors/Cbrt.h create mode 100644 src/cpu/blaze/math/functors/Ceil.h create mode 100644 src/cpu/blaze/math/functors/Conj.h create mode 100644 src/cpu/blaze/math/functors/Cos.h create mode 100644 src/cpu/blaze/math/functors/Cosh.h create mode 100644 src/cpu/blaze/math/functors/Erf.h create mode 100644 src/cpu/blaze/math/functors/Erfc.h create mode 100644 src/cpu/blaze/math/functors/Eval.h create mode 100644 src/cpu/blaze/math/functors/Exp.h create mode 100644 src/cpu/blaze/math/functors/Floor.h create mode 100644 src/cpu/blaze/math/functors/Forward.h create mode 100644 src/cpu/blaze/math/functors/Functors.h create mode 100644 src/cpu/blaze/math/functors/Imag.h create mode 100644 src/cpu/blaze/math/functors/Inv.h create mode 100644 src/cpu/blaze/math/functors/InvCbrt.h create mode 100644 src/cpu/blaze/math/functors/InvSqrt.h create mode 100644 src/cpu/blaze/math/functors/Log.h create mode 100644 src/cpu/blaze/math/functors/Log10.h create mode 100644 src/cpu/blaze/math/functors/Pow.h create mode 100644 src/cpu/blaze/math/functors/Real.h create mode 100644 src/cpu/blaze/math/functors/Serial.h create mode 100644 src/cpu/blaze/math/functors/Sin.h create mode 100644 src/cpu/blaze/math/functors/Sinh.h create mode 100644 src/cpu/blaze/math/functors/Sqrt.h create mode 100644 src/cpu/blaze/math/functors/Tan.h create mode 100644 src/cpu/blaze/math/functors/Tanh.h create mode 100644 src/cpu/blaze/math/functors/Trans.h create mode 100644 src/cpu/blaze/math/lapack/LAPACK.h create mode 100644 src/cpu/blaze/math/lapack/clapack/gelqf.h create mode 100644 src/cpu/blaze/math/lapack/clapack/geqlf.h create mode 100644 src/cpu/blaze/math/lapack/clapack/geqp3.h create mode 100644 src/cpu/blaze/math/lapack/clapack/geqrf.h create mode 100644 src/cpu/blaze/math/lapack/clapack/gerqf.h create mode 100644 src/cpu/blaze/math/lapack/clapack/gesv.h create mode 100644 src/cpu/blaze/math/lapack/clapack/getrf.h create mode 100644 src/cpu/blaze/math/lapack/clapack/getri.h create mode 100644 src/cpu/blaze/math/lapack/clapack/getrs.h create mode 100644 src/cpu/blaze/math/lapack/clapack/hesv.h create mode 100644 src/cpu/blaze/math/lapack/clapack/hetrf.h create mode 100644 src/cpu/blaze/math/lapack/clapack/hetri.h create mode 100644 src/cpu/blaze/math/lapack/clapack/hetrs.h create mode 100644 src/cpu/blaze/math/lapack/clapack/orglq.h create mode 100644 src/cpu/blaze/math/lapack/clapack/orgql.h create mode 100644 src/cpu/blaze/math/lapack/clapack/orgqr.h create mode 100644 src/cpu/blaze/math/lapack/clapack/orgrq.h create mode 100644 src/cpu/blaze/math/lapack/clapack/ormlq.h create mode 100644 src/cpu/blaze/math/lapack/clapack/ormql.h create mode 100644 src/cpu/blaze/math/lapack/clapack/ormqr.h create mode 100644 src/cpu/blaze/math/lapack/clapack/ormrq.h create mode 100644 src/cpu/blaze/math/lapack/clapack/posv.h create mode 100644 src/cpu/blaze/math/lapack/clapack/potrf.h create mode 100644 src/cpu/blaze/math/lapack/clapack/potri.h create mode 100644 src/cpu/blaze/math/lapack/clapack/potrs.h create mode 100644 src/cpu/blaze/math/lapack/clapack/sysv.h create mode 100644 src/cpu/blaze/math/lapack/clapack/sytrf.h create mode 100644 src/cpu/blaze/math/lapack/clapack/sytri.h create mode 100644 src/cpu/blaze/math/lapack/clapack/sytrs.h create mode 100644 src/cpu/blaze/math/lapack/clapack/trsv.h create mode 100644 src/cpu/blaze/math/lapack/clapack/trtri.h create mode 100644 src/cpu/blaze/math/lapack/clapack/trtrs.h create mode 100644 src/cpu/blaze/math/lapack/clapack/unglq.h create mode 100644 src/cpu/blaze/math/lapack/clapack/ungql.h create mode 100644 src/cpu/blaze/math/lapack/clapack/ungqr.h create mode 100644 src/cpu/blaze/math/lapack/clapack/ungrq.h create mode 100644 src/cpu/blaze/math/lapack/clapack/unmlq.h create mode 100644 src/cpu/blaze/math/lapack/clapack/unmql.h create mode 100644 src/cpu/blaze/math/lapack/clapack/unmqr.h create mode 100644 src/cpu/blaze/math/lapack/clapack/unmrq.h create mode 100644 src/cpu/blaze/math/lapack/gelqf.h create mode 100644 src/cpu/blaze/math/lapack/geqlf.h create mode 100644 src/cpu/blaze/math/lapack/geqp3.h create mode 100644 src/cpu/blaze/math/lapack/geqrf.h create mode 100644 src/cpu/blaze/math/lapack/gerqf.h create mode 100644 src/cpu/blaze/math/lapack/gesv.h create mode 100644 src/cpu/blaze/math/lapack/getrf.h create mode 100644 src/cpu/blaze/math/lapack/getri.h create mode 100644 src/cpu/blaze/math/lapack/getrs.h create mode 100644 src/cpu/blaze/math/lapack/hesv.h create mode 100644 src/cpu/blaze/math/lapack/hetrf.h create mode 100644 src/cpu/blaze/math/lapack/hetri.h create mode 100644 src/cpu/blaze/math/lapack/hetrs.h create mode 100644 src/cpu/blaze/math/lapack/orglq.h create mode 100644 src/cpu/blaze/math/lapack/orgql.h create mode 100644 src/cpu/blaze/math/lapack/orgqr.h create mode 100644 src/cpu/blaze/math/lapack/orgrq.h create mode 100644 src/cpu/blaze/math/lapack/ormlq.h create mode 100644 src/cpu/blaze/math/lapack/ormql.h create mode 100644 src/cpu/blaze/math/lapack/ormqr.h create mode 100644 src/cpu/blaze/math/lapack/ormrq.h create mode 100644 src/cpu/blaze/math/lapack/posv.h create mode 100644 src/cpu/blaze/math/lapack/potrf.h create mode 100644 src/cpu/blaze/math/lapack/potri.h create mode 100644 src/cpu/blaze/math/lapack/potrs.h create mode 100644 src/cpu/blaze/math/lapack/sysv.h create mode 100644 src/cpu/blaze/math/lapack/sytrf.h create mode 100644 src/cpu/blaze/math/lapack/sytri.h create mode 100644 src/cpu/blaze/math/lapack/sytrs.h create mode 100644 src/cpu/blaze/math/lapack/trsv.h create mode 100644 src/cpu/blaze/math/lapack/trtri.h create mode 100644 src/cpu/blaze/math/lapack/trtrs.h create mode 100644 src/cpu/blaze/math/lapack/unglq.h create mode 100644 src/cpu/blaze/math/lapack/ungql.h create mode 100644 src/cpu/blaze/math/lapack/ungqr.h create mode 100644 src/cpu/blaze/math/lapack/ungrq.h create mode 100644 src/cpu/blaze/math/lapack/unmlq.h create mode 100644 src/cpu/blaze/math/lapack/unmql.h create mode 100644 src/cpu/blaze/math/lapack/unmqr.h create mode 100644 src/cpu/blaze/math/lapack/unmrq.h create mode 100644 src/cpu/blaze/math/proxy/ComplexProxy.h create mode 100644 src/cpu/blaze/math/proxy/DefaultProxy.h create mode 100644 src/cpu/blaze/math/proxy/DenseMatrixProxy.h create mode 100644 src/cpu/blaze/math/proxy/DenseVectorProxy.h create mode 100644 src/cpu/blaze/math/proxy/Forward.h create mode 100644 src/cpu/blaze/math/proxy/Proxy.h create mode 100644 src/cpu/blaze/math/proxy/SparseMatrixProxy.h create mode 100644 src/cpu/blaze/math/proxy/SparseVectorProxy.h create mode 100644 src/cpu/blaze/math/serialization/MatrixSerializer.h create mode 100644 src/cpu/blaze/math/serialization/Serialization.h create mode 100644 src/cpu/blaze/math/serialization/TypeValueMapping.h create mode 100644 src/cpu/blaze/math/serialization/VectorSerializer.h create mode 100644 src/cpu/blaze/math/shims/Abs.h create mode 100644 src/cpu/blaze/math/shims/Acos.h create mode 100644 src/cpu/blaze/math/shims/Acosh.h create mode 100644 src/cpu/blaze/math/shims/Asin.h create mode 100644 src/cpu/blaze/math/shims/Asinh.h create mode 100644 src/cpu/blaze/math/shims/Atan.h create mode 100644 src/cpu/blaze/math/shims/Atanh.h create mode 100644 src/cpu/blaze/math/shims/Cbrt.h create mode 100644 src/cpu/blaze/math/shims/Ceil.h create mode 100644 src/cpu/blaze/math/shims/Clear.h create mode 100644 src/cpu/blaze/math/shims/Conjugate.h create mode 100644 src/cpu/blaze/math/shims/Cos.h create mode 100644 src/cpu/blaze/math/shims/Cosh.h create mode 100644 src/cpu/blaze/math/shims/Equal.h create mode 100644 src/cpu/blaze/math/shims/Erf.h create mode 100644 src/cpu/blaze/math/shims/Erfc.h create mode 100644 src/cpu/blaze/math/shims/Exp.h create mode 100644 src/cpu/blaze/math/shims/Floor.h create mode 100644 src/cpu/blaze/math/shims/Imaginary.h create mode 100644 src/cpu/blaze/math/shims/InvCbrt.h create mode 100644 src/cpu/blaze/math/shims/InvSqrt.h create mode 100644 src/cpu/blaze/math/shims/Invert.h create mode 100644 src/cpu/blaze/math/shims/IsDefault.h create mode 100644 src/cpu/blaze/math/shims/IsDivisor.h create mode 100644 src/cpu/blaze/math/shims/IsNaN.h create mode 100644 src/cpu/blaze/math/shims/IsOne.h create mode 100644 src/cpu/blaze/math/shims/IsReal.h create mode 100644 src/cpu/blaze/math/shims/IsZero.h create mode 100644 src/cpu/blaze/math/shims/Log.h create mode 100644 src/cpu/blaze/math/shims/Log10.h create mode 100644 src/cpu/blaze/math/shims/Pow.h create mode 100644 src/cpu/blaze/math/shims/Real.h create mode 100644 src/cpu/blaze/math/shims/Reset.h create mode 100644 src/cpu/blaze/math/shims/Serial.h create mode 100644 src/cpu/blaze/math/shims/Shims.h create mode 100644 src/cpu/blaze/math/shims/Sin.h create mode 100644 src/cpu/blaze/math/shims/Sinh.h create mode 100644 src/cpu/blaze/math/shims/Sqrt.h create mode 100644 src/cpu/blaze/math/shims/Square.h create mode 100644 src/cpu/blaze/math/shims/Tan.h create mode 100644 src/cpu/blaze/math/shims/Tanh.h create mode 100644 src/cpu/blaze/math/simd/Abs.h create mode 100644 src/cpu/blaze/math/simd/Acos.h create mode 100644 src/cpu/blaze/math/simd/Acosh.h create mode 100644 src/cpu/blaze/math/simd/Addition.h create mode 100644 src/cpu/blaze/math/simd/Asin.h create mode 100644 src/cpu/blaze/math/simd/Asinh.h create mode 100644 src/cpu/blaze/math/simd/Atan.h create mode 100644 src/cpu/blaze/math/simd/Atanh.h create mode 100644 src/cpu/blaze/math/simd/BasicTypes.h create mode 100644 src/cpu/blaze/math/simd/Cbrt.h create mode 100644 src/cpu/blaze/math/simd/Ceil.h create mode 100644 src/cpu/blaze/math/simd/Conj.h create mode 100644 src/cpu/blaze/math/simd/Cos.h create mode 100644 src/cpu/blaze/math/simd/Cosh.h create mode 100644 src/cpu/blaze/math/simd/DerivedTypes.h create mode 100644 src/cpu/blaze/math/simd/Division.h create mode 100644 src/cpu/blaze/math/simd/Erf.h create mode 100644 src/cpu/blaze/math/simd/Erfc.h create mode 100644 src/cpu/blaze/math/simd/Exp.h create mode 100644 src/cpu/blaze/math/simd/FMA.h create mode 100644 src/cpu/blaze/math/simd/Floor.h create mode 100644 src/cpu/blaze/math/simd/Functions.h create mode 100644 src/cpu/blaze/math/simd/InvCbrt.h create mode 100644 src/cpu/blaze/math/simd/InvSqrt.h create mode 100644 src/cpu/blaze/math/simd/Loada.h create mode 100644 src/cpu/blaze/math/simd/Loadu.h create mode 100644 src/cpu/blaze/math/simd/Log.h create mode 100644 src/cpu/blaze/math/simd/Log10.h create mode 100644 src/cpu/blaze/math/simd/Multiplication.h create mode 100644 src/cpu/blaze/math/simd/Pow.h create mode 100644 src/cpu/blaze/math/simd/Reduction.h create mode 100644 src/cpu/blaze/math/simd/SIMD.h create mode 100644 src/cpu/blaze/math/simd/SIMDPack.h create mode 100644 src/cpu/blaze/math/simd/SIMDTrait.h create mode 100644 src/cpu/blaze/math/simd/Set.h create mode 100644 src/cpu/blaze/math/simd/Setzero.h create mode 100644 src/cpu/blaze/math/simd/Sin.h create mode 100644 src/cpu/blaze/math/simd/Sinh.h create mode 100644 src/cpu/blaze/math/simd/Sqrt.h create mode 100644 src/cpu/blaze/math/simd/Storea.h create mode 100644 src/cpu/blaze/math/simd/Storeu.h create mode 100644 src/cpu/blaze/math/simd/Stream.h create mode 100644 src/cpu/blaze/math/simd/Subtraction.h create mode 100644 src/cpu/blaze/math/simd/Tan.h create mode 100644 src/cpu/blaze/math/simd/Tanh.h create mode 100644 src/cpu/blaze/math/smp/DenseMatrix.h create mode 100644 src/cpu/blaze/math/smp/DenseVector.h create mode 100644 src/cpu/blaze/math/smp/Functions.h create mode 100644 src/cpu/blaze/math/smp/ParallelSection.h create mode 100644 src/cpu/blaze/math/smp/SMP.h create mode 100644 src/cpu/blaze/math/smp/SerialSection.h create mode 100644 src/cpu/blaze/math/smp/SparseMatrix.h create mode 100644 src/cpu/blaze/math/smp/SparseVector.h create mode 100644 src/cpu/blaze/math/smp/default/DenseMatrix.h create mode 100644 src/cpu/blaze/math/smp/default/DenseVector.h create mode 100644 src/cpu/blaze/math/smp/default/Functions.h create mode 100644 src/cpu/blaze/math/smp/default/SparseMatrix.h create mode 100644 src/cpu/blaze/math/smp/default/SparseVector.h create mode 100644 src/cpu/blaze/math/smp/openmp/DenseMatrix.h create mode 100644 src/cpu/blaze/math/smp/openmp/DenseVector.h create mode 100644 src/cpu/blaze/math/smp/openmp/Functions.h create mode 100644 src/cpu/blaze/math/smp/threads/DenseMatrix.h create mode 100644 src/cpu/blaze/math/smp/threads/DenseVector.h create mode 100644 src/cpu/blaze/math/smp/threads/Functions.h create mode 100644 src/cpu/blaze/math/smp/threads/ThreadBackend.h create mode 100644 src/cpu/blaze/math/sparse/CompressedMatrix.h create mode 100644 src/cpu/blaze/math/sparse/CompressedVector.h create mode 100644 src/cpu/blaze/math/sparse/Forward.h create mode 100644 src/cpu/blaze/math/sparse/MatrixAccessProxy.h create mode 100644 src/cpu/blaze/math/sparse/SparseElement.h create mode 100644 src/cpu/blaze/math/sparse/SparseMatrix.h create mode 100644 src/cpu/blaze/math/sparse/SparseVector.h create mode 100644 src/cpu/blaze/math/sparse/ValueIndexPair.h create mode 100644 src/cpu/blaze/math/sparse/VectorAccessProxy.h create mode 100644 src/cpu/blaze/math/traits/AddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/AddTrait.h create mode 100644 src/cpu/blaze/math/traits/CTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/ColumnExprTrait.h create mode 100644 src/cpu/blaze/math/traits/ColumnTrait.h create mode 100644 src/cpu/blaze/math/traits/CrossExprTrait.h create mode 100644 src/cpu/blaze/math/traits/CrossTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatCTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatDMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatDMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatDMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatDVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatEvalExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatForEachExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatInvExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatSMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatSMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatSMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatSVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatScalarDivExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatScalarMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatSerialExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatTDMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatTDMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatTDMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatTSMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatTSMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatTSMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DMatTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecCTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecDVecAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecDVecCrossExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecDVecDivExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecDVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecDVecSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecEvalExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecForEachExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecSVecAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecSVecCrossExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecSVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecSVecSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecScalarDivExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecScalarMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecSerialExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecTDVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecTSVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DVecTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DerestrictTrait.h create mode 100644 src/cpu/blaze/math/traits/DivExprTrait.h create mode 100644 src/cpu/blaze/math/traits/DivTrait.h create mode 100644 src/cpu/blaze/math/traits/EvalExprTrait.h create mode 100644 src/cpu/blaze/math/traits/ForEachExprTrait.h create mode 100644 src/cpu/blaze/math/traits/ForEachTrait.h create mode 100644 src/cpu/blaze/math/traits/ImagTrait.h create mode 100644 src/cpu/blaze/math/traits/InvExprTrait.h create mode 100644 src/cpu/blaze/math/traits/MathTrait.h create mode 100644 src/cpu/blaze/math/traits/MultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/MultTrait.h create mode 100644 src/cpu/blaze/math/traits/RealTrait.h create mode 100644 src/cpu/blaze/math/traits/RowExprTrait.h create mode 100644 src/cpu/blaze/math/traits/RowTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatCTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatDMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatDMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatDMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatDVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatEvalExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatForEachExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatSMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatSMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatSMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatSVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatScalarDivExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatScalarMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatSerialExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatTDMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatTDMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatTDMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatTSMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatTSMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatTSMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SMatTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecCTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecDVecAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecDVecCrossExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecDVecDivExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecDVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecDVecSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecEvalExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecForEachExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecSVecAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecSVecCrossExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecSVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecSVecSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecScalarDivExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecScalarMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecSerialExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecTDVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecTSVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SVecTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SerialExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SubTrait.h create mode 100644 src/cpu/blaze/math/traits/SubmatrixExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SubmatrixTrait.h create mode 100644 src/cpu/blaze/math/traits/SubvectorExprTrait.h create mode 100644 src/cpu/blaze/math/traits/SubvectorTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatCTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatDMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatDMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatDMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatDVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatEvalExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatForEachExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatInvExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatSMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatSMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatSMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatSVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatScalarDivExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatScalarMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatSerialExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatTDMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatTDMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatTDMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatTSMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatTSMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatTSMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDMatTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecCTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecDMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecDVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecEvalExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecForEachExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecSMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecSVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecScalarDivExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecScalarMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecSerialExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecTDMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecTDVecAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecTDVecCrossExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecTDVecDivExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecTDVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecTDVecSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecTSMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecTSVecAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecTSVecCrossExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecTSVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecTSVecSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TDVecTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatCTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatDMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatDMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatDMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatDVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatEvalExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatForEachExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatSMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatSMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatSMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatSVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatScalarDivExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatScalarMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatSerialExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatTDMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatTDMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatTDMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatTSMatAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatTSMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatTSMatSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSMatTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecCTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecDMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecDVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecEvalExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecForEachExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecSMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecSVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecScalarDivExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecScalarMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecSerialExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecTDMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecTDVecAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecTDVecCrossExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecTDVecDivExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecTDVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecTDVecSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecTSMatMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecTSVecAddExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecTSVecCrossExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecTSVecMultExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecTSVecSubExprTrait.h create mode 100644 src/cpu/blaze/math/traits/TSVecTransExprTrait.h create mode 100644 src/cpu/blaze/math/traits/Traits.h create mode 100644 src/cpu/blaze/math/traits/TransExprTrait.h create mode 100644 src/cpu/blaze/math/typetraits/AreSIMDCombinable.h create mode 100644 src/cpu/blaze/math/typetraits/Columns.h create mode 100644 src/cpu/blaze/math/typetraits/HasConstDataAccess.h create mode 100644 src/cpu/blaze/math/typetraits/HasMutableDataAccess.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDAbs.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDAcos.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDAcosh.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDAdd.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDAsin.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDAsinh.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDAtan.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDAtanh.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDCbrt.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDCeil.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDConj.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDCos.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDCosh.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDDiv.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDErf.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDErfc.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDExp.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDFloor.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDInvCbrt.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDInvSqrt.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDLog.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDLog10.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDMult.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDPow.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDSin.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDSinh.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDSqrt.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDSub.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDTan.h create mode 100644 src/cpu/blaze/math/typetraits/HasSIMDTanh.h create mode 100644 src/cpu/blaze/math/typetraits/IsAdaptor.h create mode 100644 src/cpu/blaze/math/typetraits/IsAddExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsAligned.h create mode 100644 src/cpu/blaze/math/typetraits/IsBLASCompatible.h create mode 100644 src/cpu/blaze/math/typetraits/IsColumn.h create mode 100644 src/cpu/blaze/math/typetraits/IsColumnMajorMatrix.h create mode 100644 src/cpu/blaze/math/typetraits/IsColumnVector.h create mode 100644 src/cpu/blaze/math/typetraits/IsComputation.h create mode 100644 src/cpu/blaze/math/typetraits/IsCrossExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsCustom.h create mode 100644 src/cpu/blaze/math/typetraits/IsDenseMatrix.h create mode 100644 src/cpu/blaze/math/typetraits/IsDenseVector.h create mode 100644 src/cpu/blaze/math/typetraits/IsDiagonal.h create mode 100644 src/cpu/blaze/math/typetraits/IsDivExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsEvalExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsExpression.h create mode 100644 src/cpu/blaze/math/typetraits/IsForEachExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsGeneral.h create mode 100644 src/cpu/blaze/math/typetraits/IsHermitian.h create mode 100644 src/cpu/blaze/math/typetraits/IsIdentity.h create mode 100644 src/cpu/blaze/math/typetraits/IsInvertible.h create mode 100644 src/cpu/blaze/math/typetraits/IsLower.h create mode 100644 src/cpu/blaze/math/typetraits/IsMatEvalExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsMatForEachExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsMatInvExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsMatMatAddExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsMatMatMultExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsMatMatSubExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsMatScalarDivExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsMatScalarMultExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsMatSerialExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsMatTransExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsMatVecMultExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsMatrix.h create mode 100644 src/cpu/blaze/math/typetraits/IsMultExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsNumericMatrix.h create mode 100644 src/cpu/blaze/math/typetraits/IsNumericVector.h create mode 100644 src/cpu/blaze/math/typetraits/IsOpposedView.h create mode 100644 src/cpu/blaze/math/typetraits/IsPadded.h create mode 100644 src/cpu/blaze/math/typetraits/IsProxy.h create mode 100644 src/cpu/blaze/math/typetraits/IsResizable.h create mode 100644 src/cpu/blaze/math/typetraits/IsRestricted.h create mode 100644 src/cpu/blaze/math/typetraits/IsRow.h create mode 100644 src/cpu/blaze/math/typetraits/IsRowMajorMatrix.h create mode 100644 src/cpu/blaze/math/typetraits/IsRowVector.h create mode 100644 src/cpu/blaze/math/typetraits/IsSIMDEnabled.h create mode 100644 src/cpu/blaze/math/typetraits/IsSIMDPack.h create mode 100644 src/cpu/blaze/math/typetraits/IsSMPAssignable.h create mode 100644 src/cpu/blaze/math/typetraits/IsSerialExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsSparseElement.h create mode 100644 src/cpu/blaze/math/typetraits/IsSparseMatrix.h create mode 100644 src/cpu/blaze/math/typetraits/IsSparseVector.h create mode 100644 src/cpu/blaze/math/typetraits/IsSquare.h create mode 100644 src/cpu/blaze/math/typetraits/IsStrictlyLower.h create mode 100644 src/cpu/blaze/math/typetraits/IsStrictlyTriangular.h create mode 100644 src/cpu/blaze/math/typetraits/IsStrictlyUpper.h create mode 100644 src/cpu/blaze/math/typetraits/IsSubExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsSubmatrix.h create mode 100644 src/cpu/blaze/math/typetraits/IsSubvector.h create mode 100644 src/cpu/blaze/math/typetraits/IsSymmetric.h create mode 100644 src/cpu/blaze/math/typetraits/IsTVecMatMultExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsTemporary.h create mode 100644 src/cpu/blaze/math/typetraits/IsTransExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsTriangular.h create mode 100644 src/cpu/blaze/math/typetraits/IsUniLower.h create mode 100644 src/cpu/blaze/math/typetraits/IsUniTriangular.h create mode 100644 src/cpu/blaze/math/typetraits/IsUniUpper.h create mode 100644 src/cpu/blaze/math/typetraits/IsUpper.h create mode 100644 src/cpu/blaze/math/typetraits/IsVecEvalExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsVecForEachExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsVecScalarDivExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsVecScalarMultExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsVecSerialExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsVecTVecMultExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsVecTransExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsVecVecAddExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsVecVecDivExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsVecVecMultExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsVecVecSubExpr.h create mode 100644 src/cpu/blaze/math/typetraits/IsVector.h create mode 100644 src/cpu/blaze/math/typetraits/IsView.h create mode 100644 src/cpu/blaze/math/typetraits/RemoveAdaptor.h create mode 100644 src/cpu/blaze/math/typetraits/RequiresEvaluation.h create mode 100644 src/cpu/blaze/math/typetraits/Rows.h create mode 100644 src/cpu/blaze/math/typetraits/Size.h create mode 100644 src/cpu/blaze/math/typetraits/StorageOrder.h create mode 100644 src/cpu/blaze/math/typetraits/TransposeFlag.h create mode 100644 src/cpu/blaze/math/typetraits/TypeTraits.h create mode 100644 src/cpu/blaze/math/typetraits/UnderlyingBuiltin.h create mode 100644 src/cpu/blaze/math/typetraits/UnderlyingElement.h create mode 100644 src/cpu/blaze/math/typetraits/UnderlyingNumeric.h create mode 100644 src/cpu/blaze/math/views/Column.h create mode 100644 src/cpu/blaze/math/views/Forward.h create mode 100644 src/cpu/blaze/math/views/Row.h create mode 100644 src/cpu/blaze/math/views/Submatrix.h create mode 100644 src/cpu/blaze/math/views/Subvector.h create mode 100644 src/cpu/blaze/math/views/Views.h create mode 100644 src/cpu/blaze/math/views/column/BaseTemplate.h create mode 100644 src/cpu/blaze/math/views/column/Dense.h create mode 100644 src/cpu/blaze/math/views/column/Sparse.h create mode 100644 src/cpu/blaze/math/views/row/BaseTemplate.h create mode 100644 src/cpu/blaze/math/views/row/Dense.h create mode 100644 src/cpu/blaze/math/views/row/Sparse.h create mode 100644 src/cpu/blaze/math/views/submatrix/BaseTemplate.h create mode 100644 src/cpu/blaze/math/views/submatrix/Dense.h create mode 100644 src/cpu/blaze/math/views/submatrix/Sparse.h create mode 100644 src/cpu/blaze/math/views/subvector/BaseTemplate.h create mode 100644 src/cpu/blaze/math/views/subvector/Dense.h create mode 100644 src/cpu/blaze/math/views/subvector/Sparse.h create mode 100644 src/cpu/blaze/system/Assertion.h create mode 100644 src/cpu/blaze/system/BLAS.h create mode 100644 src/cpu/blaze/system/Blocking.h create mode 100644 src/cpu/blaze/system/CacheSize.h create mode 100644 src/cpu/blaze/system/Debugging.h create mode 100644 src/cpu/blaze/system/Deprecated.h create mode 100644 src/cpu/blaze/system/Inline.h create mode 100644 src/cpu/blaze/system/Logging.h create mode 100644 src/cpu/blaze/system/MPI.h create mode 100644 src/cpu/blaze/system/Optimizations.h create mode 100644 src/cpu/blaze/system/Precision.h create mode 100644 src/cpu/blaze/system/Random.h create mode 100644 src/cpu/blaze/system/Restrict.h create mode 100644 src/cpu/blaze/system/SMP.h create mode 100644 src/cpu/blaze/system/Signature.h create mode 100644 src/cpu/blaze/system/StorageOrder.h create mode 100644 src/cpu/blaze/system/System.h create mode 100644 src/cpu/blaze/system/Thresholds.h create mode 100644 src/cpu/blaze/system/TransposeFlag.h create mode 100644 src/cpu/blaze/system/Vectorization.h create mode 100644 src/cpu/blaze/system/Version.h create mode 100644 src/cpu/blaze/system/WarningDisable.h create mode 100644 src/cpu/blaze/util/Algorithm.h create mode 100644 src/cpu/blaze/util/AlignedAllocator.h create mode 100644 src/cpu/blaze/util/AlignedArray.h create mode 100644 src/cpu/blaze/util/AlignmentCheck.h create mode 100644 src/cpu/blaze/util/Assert.h create mode 100644 src/cpu/blaze/util/ColorMacros.h create mode 100644 src/cpu/blaze/util/Complex.h create mode 100644 src/cpu/blaze/util/Constraints.h create mode 100644 src/cpu/blaze/util/Convert.h create mode 100644 src/cpu/blaze/util/DimensionOf.h create mode 100644 src/cpu/blaze/util/DisableIf.h create mode 100644 src/cpu/blaze/util/EmptyType.h create mode 100644 src/cpu/blaze/util/EnableIf.h create mode 100644 src/cpu/blaze/util/Exception.h create mode 100644 src/cpu/blaze/util/FalseType.h create mode 100644 src/cpu/blaze/util/Indices.h create mode 100644 src/cpu/blaze/util/InputString.h create mode 100644 src/cpu/blaze/util/IntegralConstant.h create mode 100644 src/cpu/blaze/util/InvalidType.h create mode 100644 src/cpu/blaze/util/Limits.h create mode 100644 src/cpu/blaze/util/Logging.h create mode 100644 src/cpu/blaze/util/MPL.h create mode 100644 src/cpu/blaze/util/Memory.h create mode 100644 src/cpu/blaze/util/MemoryPool.h create mode 100644 src/cpu/blaze/util/Misalignment.h create mode 100644 src/cpu/blaze/util/NonCopyable.h create mode 100644 src/cpu/blaze/util/NonCreatable.h create mode 100644 src/cpu/blaze/util/NullType.h create mode 100644 src/cpu/blaze/util/PointerCast.h create mode 100644 src/cpu/blaze/util/Policies.h create mode 100644 src/cpu/blaze/util/PtrIterator.h create mode 100644 src/cpu/blaze/util/PtrVector.h create mode 100644 src/cpu/blaze/util/Random.h create mode 100644 src/cpu/blaze/util/Serialization.h create mode 100644 src/cpu/blaze/util/Singleton.h create mode 100644 src/cpu/blaze/util/StaticAssert.h create mode 100644 src/cpu/blaze/util/Suffix.h create mode 100644 src/cpu/blaze/util/SystemClock.h create mode 100644 src/cpu/blaze/util/SystemClockID.h create mode 100644 src/cpu/blaze/util/Template.h create mode 100644 src/cpu/blaze/util/Thread.h create mode 100644 src/cpu/blaze/util/ThreadPool.h create mode 100644 src/cpu/blaze/util/Time.h create mode 100644 src/cpu/blaze/util/Timing.h create mode 100644 src/cpu/blaze/util/TrueType.h create mode 100644 src/cpu/blaze/util/TypeList.h create mode 100644 src/cpu/blaze/util/TypeTraits.h create mode 100644 src/cpu/blaze/util/Types.h create mode 100644 src/cpu/blaze/util/UnsignedValue.h create mode 100644 src/cpu/blaze/util/Unused.h create mode 100644 src/cpu/blaze/util/Util.h create mode 100644 src/cpu/blaze/util/ValueTraits.h create mode 100644 src/cpu/blaze/util/constraints/Arithmetic.h create mode 100644 src/cpu/blaze/util/constraints/Array.h create mode 100644 src/cpu/blaze/util/constraints/Assignable.h create mode 100644 src/cpu/blaze/util/constraints/BaseOf.h create mode 100644 src/cpu/blaze/util/constraints/Boolean.h create mode 100644 src/cpu/blaze/util/constraints/Builtin.h create mode 100644 src/cpu/blaze/util/constraints/Class.h create mode 100644 src/cpu/blaze/util/constraints/Comparable.h create mode 100644 src/cpu/blaze/util/constraints/Complex.h create mode 100644 src/cpu/blaze/util/constraints/ComplexDouble.h create mode 100644 src/cpu/blaze/util/constraints/ComplexFloat.h create mode 100644 src/cpu/blaze/util/constraints/Const.h create mode 100644 src/cpu/blaze/util/constraints/Constraints.h create mode 100644 src/cpu/blaze/util/constraints/Constructible.h create mode 100644 src/cpu/blaze/util/constraints/Convertible.h create mode 100644 src/cpu/blaze/util/constraints/DerivedFrom.h create mode 100644 src/cpu/blaze/util/constraints/Destructible.h create mode 100644 src/cpu/blaze/util/constraints/Double.h create mode 100644 src/cpu/blaze/util/constraints/Empty.h create mode 100644 src/cpu/blaze/util/constraints/Float.h create mode 100644 src/cpu/blaze/util/constraints/FloatingPoint.h create mode 100644 src/cpu/blaze/util/constraints/Integer.h create mode 100644 src/cpu/blaze/util/constraints/Integral.h create mode 100644 src/cpu/blaze/util/constraints/LongDouble.h create mode 100644 src/cpu/blaze/util/constraints/Numeric.h create mode 100644 src/cpu/blaze/util/constraints/Object.h create mode 100644 src/cpu/blaze/util/constraints/Pod.h create mode 100644 src/cpu/blaze/util/constraints/Pointer.h create mode 100644 src/cpu/blaze/util/constraints/Rank.h create mode 100644 src/cpu/blaze/util/constraints/Reference.h create mode 100644 src/cpu/blaze/util/constraints/SameSize.h create mode 100644 src/cpu/blaze/util/constraints/SameType.h create mode 100644 src/cpu/blaze/util/constraints/Signed.h create mode 100644 src/cpu/blaze/util/constraints/Size.h create mode 100644 src/cpu/blaze/util/constraints/Subscriptable.h create mode 100644 src/cpu/blaze/util/constraints/TypeRestriction.h create mode 100644 src/cpu/blaze/util/constraints/Union.h create mode 100644 src/cpu/blaze/util/constraints/Unsigned.h create mode 100644 src/cpu/blaze/util/constraints/Valid.h create mode 100644 src/cpu/blaze/util/constraints/Vectorizable.h create mode 100644 src/cpu/blaze/util/constraints/Void.h create mode 100644 src/cpu/blaze/util/constraints/Volatile.h create mode 100644 src/cpu/blaze/util/logging/DebugSection.h create mode 100644 src/cpu/blaze/util/logging/DetailSection.h create mode 100644 src/cpu/blaze/util/logging/ErrorSection.h create mode 100644 src/cpu/blaze/util/logging/FunctionTrace.h create mode 100644 src/cpu/blaze/util/logging/InfoSection.h create mode 100644 src/cpu/blaze/util/logging/LogLevel.h create mode 100644 src/cpu/blaze/util/logging/LogSection.h create mode 100644 src/cpu/blaze/util/logging/Logger.h create mode 100644 src/cpu/blaze/util/logging/Logging.h create mode 100644 src/cpu/blaze/util/logging/ProgressSection.h create mode 100644 src/cpu/blaze/util/logging/WarningSection.h create mode 100644 src/cpu/blaze/util/mpl/And.h create mode 100644 src/cpu/blaze/util/mpl/Bool.h create mode 100644 src/cpu/blaze/util/mpl/Char.h create mode 100644 src/cpu/blaze/util/mpl/Equal.h create mode 100644 src/cpu/blaze/util/mpl/Greater.h create mode 100644 src/cpu/blaze/util/mpl/If.h create mode 100644 src/cpu/blaze/util/mpl/Int.h create mode 100644 src/cpu/blaze/util/mpl/Less.h create mode 100644 src/cpu/blaze/util/mpl/Long.h create mode 100644 src/cpu/blaze/util/mpl/MPL.h create mode 100644 src/cpu/blaze/util/mpl/Max.h create mode 100644 src/cpu/blaze/util/mpl/Min.h create mode 100644 src/cpu/blaze/util/mpl/Minus.h create mode 100644 src/cpu/blaze/util/mpl/Modulus.h create mode 100644 src/cpu/blaze/util/mpl/NextMultiple.h create mode 100644 src/cpu/blaze/util/mpl/Not.h create mode 100644 src/cpu/blaze/util/mpl/Or.h create mode 100644 src/cpu/blaze/util/mpl/Plus.h create mode 100644 src/cpu/blaze/util/mpl/SizeT.h create mode 100644 src/cpu/blaze/util/mpl/Times.h create mode 100644 src/cpu/blaze/util/mpl/Xor.h create mode 100644 src/cpu/blaze/util/policies/ArrayDelete.h create mode 100644 src/cpu/blaze/util/policies/ConstantGrowth.h create mode 100644 src/cpu/blaze/util/policies/Deallocate.h create mode 100644 src/cpu/blaze/util/policies/DefaultDelete.h create mode 100644 src/cpu/blaze/util/policies/LinearGrowth.h create mode 100644 src/cpu/blaze/util/policies/NoDelete.h create mode 100644 src/cpu/blaze/util/policies/OptimalGrowth.h create mode 100644 src/cpu/blaze/util/policies/PtrDelete.h create mode 100644 src/cpu/blaze/util/serialization/Archive.h create mode 100644 src/cpu/blaze/util/serialization/Serialization.h create mode 100644 src/cpu/blaze/util/singleton/Dependency.h create mode 100644 src/cpu/blaze/util/singleton/Singleton.h create mode 100644 src/cpu/blaze/util/threadpool/Task.h create mode 100644 src/cpu/blaze/util/threadpool/TaskQueue.h create mode 100644 src/cpu/blaze/util/threadpool/ThreadPool.h create mode 100644 src/cpu/blaze/util/timing/CpuPolicy.h create mode 100644 src/cpu/blaze/util/timing/CpuTimer.h create mode 100644 src/cpu/blaze/util/timing/Timer.h create mode 100644 src/cpu/blaze/util/timing/Timing.h create mode 100644 src/cpu/blaze/util/timing/WcPolicy.h create mode 100644 src/cpu/blaze/util/timing/WcTimer.h create mode 100644 src/cpu/blaze/util/typetraits/AddCV.h create mode 100644 src/cpu/blaze/util/typetraits/AddConst.h create mode 100644 src/cpu/blaze/util/typetraits/AddPointer.h create mode 100644 src/cpu/blaze/util/typetraits/AddReference.h create mode 100644 src/cpu/blaze/util/typetraits/AddVolatile.h create mode 100644 src/cpu/blaze/util/typetraits/AlignmentOf.h create mode 100644 src/cpu/blaze/util/typetraits/All.h create mode 100644 src/cpu/blaze/util/typetraits/Any.h create mode 100644 src/cpu/blaze/util/typetraits/CommonType.h create mode 100644 src/cpu/blaze/util/typetraits/Decay.h create mode 100644 src/cpu/blaze/util/typetraits/Extent.h create mode 100644 src/cpu/blaze/util/typetraits/GetMemberType.h create mode 100644 src/cpu/blaze/util/typetraits/HasMember.h create mode 100644 src/cpu/blaze/util/typetraits/HasSize.h create mode 100644 src/cpu/blaze/util/typetraits/HaveSameSize.h create mode 100644 src/cpu/blaze/util/typetraits/IsArithmetic.h create mode 100644 src/cpu/blaze/util/typetraits/IsArray.h create mode 100644 src/cpu/blaze/util/typetraits/IsAssignable.h create mode 100644 src/cpu/blaze/util/typetraits/IsBaseOf.h create mode 100644 src/cpu/blaze/util/typetraits/IsBoolean.h create mode 100644 src/cpu/blaze/util/typetraits/IsBuiltin.h create mode 100644 src/cpu/blaze/util/typetraits/IsCharacter.h create mode 100644 src/cpu/blaze/util/typetraits/IsClass.h create mode 100644 src/cpu/blaze/util/typetraits/IsComplex.h create mode 100644 src/cpu/blaze/util/typetraits/IsComplexDouble.h create mode 100644 src/cpu/blaze/util/typetraits/IsComplexFloat.h create mode 100644 src/cpu/blaze/util/typetraits/IsConst.h create mode 100644 src/cpu/blaze/util/typetraits/IsConstructible.h create mode 100644 src/cpu/blaze/util/typetraits/IsConvertible.h create mode 100644 src/cpu/blaze/util/typetraits/IsDestructible.h create mode 100644 src/cpu/blaze/util/typetraits/IsDouble.h create mode 100644 src/cpu/blaze/util/typetraits/IsEmpty.h create mode 100644 src/cpu/blaze/util/typetraits/IsFloat.h create mode 100644 src/cpu/blaze/util/typetraits/IsFloatingPoint.h create mode 100644 src/cpu/blaze/util/typetraits/IsInteger.h create mode 100644 src/cpu/blaze/util/typetraits/IsIntegral.h create mode 100644 src/cpu/blaze/util/typetraits/IsLong.h create mode 100644 src/cpu/blaze/util/typetraits/IsLongDouble.h create mode 100644 src/cpu/blaze/util/typetraits/IsNumeric.h create mode 100644 src/cpu/blaze/util/typetraits/IsObject.h create mode 100644 src/cpu/blaze/util/typetraits/IsPod.h create mode 100644 src/cpu/blaze/util/typetraits/IsPointer.h create mode 100644 src/cpu/blaze/util/typetraits/IsReference.h create mode 100644 src/cpu/blaze/util/typetraits/IsSame.h create mode 100644 src/cpu/blaze/util/typetraits/IsShort.h create mode 100644 src/cpu/blaze/util/typetraits/IsSigned.h create mode 100644 src/cpu/blaze/util/typetraits/IsUnion.h create mode 100644 src/cpu/blaze/util/typetraits/IsUnsigned.h create mode 100644 src/cpu/blaze/util/typetraits/IsValid.h create mode 100644 src/cpu/blaze/util/typetraits/IsVectorizable.h create mode 100644 src/cpu/blaze/util/typetraits/IsVoid.h create mode 100644 src/cpu/blaze/util/typetraits/IsVolatile.h create mode 100644 src/cpu/blaze/util/typetraits/MakeSigned.h create mode 100644 src/cpu/blaze/util/typetraits/MakeUnsigned.h create mode 100644 src/cpu/blaze/util/typetraits/Rank.h create mode 100644 src/cpu/blaze/util/typetraits/RemoveAllExtents.h create mode 100644 src/cpu/blaze/util/typetraits/RemoveCV.h create mode 100644 src/cpu/blaze/util/typetraits/RemoveConst.h create mode 100644 src/cpu/blaze/util/typetraits/RemoveExtent.h create mode 100644 src/cpu/blaze/util/typetraits/RemovePointer.h create mode 100644 src/cpu/blaze/util/typetraits/RemoveReference.h create mode 100644 src/cpu/blaze/util/typetraits/RemoveVolatile.h create mode 100644 src/cpu/blaze/util/typetraits/TypeTraits.h create mode 100644 src/cpu/blaze/util/valuetraits/IsEven.h create mode 100644 src/cpu/blaze/util/valuetraits/IsMultipleOf.h create mode 100644 src/cpu/blaze/util/valuetraits/IsOdd.h create mode 100644 src/cpu/blaze/util/valuetraits/IsPowerOf.h create mode 100644 src/cpu/blaze/util/valuetraits/ValueTraits.h create mode 100644 src/cpu/dl4mt/decoder.h create mode 100644 src/cpu/dl4mt/dl4mt.h create mode 100644 src/cpu/dl4mt/encoder.cpp create mode 100644 src/cpu/dl4mt/encoder.h create mode 100644 src/cpu/dl4mt/gru.h create mode 100644 src/cpu/dl4mt/model.cpp create mode 100644 src/cpu/dl4mt/model.h create mode 100644 src/cpu/mblas/matrix.cpp create mode 100644 src/cpu/mblas/matrix.h create mode 100644 src/cpu/mblas/phoenix_functions.cpp create mode 100644 src/cpu/mblas/phoenix_functions.h create mode 100644 src/cpu/mblas/simd_math_prims.h create mode 100644 src/cpu/npz_converter.h 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 @@ + - + @@ -153,10 +154,10 @@ - + - + diff --git a/amunmt/.project b/amunmt/.project index 6ce9f5d6..9bcd1175 100644 --- a/amunmt/.project +++ b/amunmt/.project @@ -35,6 +35,11 @@ 2 PARENT-1-PROJECT_LOC/src/common + + cpu + 2 + PARENT-1-PROJECT_LOC/src/cpu + gpu 2 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 $ $ $ 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 +#include + + + + +//================================================================================================= +// +// 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +// +//
    +//
  • \ref configuration_and_installation
  • +//
  • \ref getting_started
  • +//
  • \ref vectors +//
      +//
    • \ref vector_types
    • +//
    • \ref vector_operations
    • +//
    +//
  • +//
  • \ref matrices +//
      +//
    • \ref matrix_types
    • +//
    • \ref matrix_operations
    • +//
    +//
  • +//
  • \ref adaptors +//
      +//
    • \ref adaptors_symmetric_matrices
    • +//
    • \ref adaptors_hermitian_matrices
    • +//
    • \ref adaptors_triangular_matrices
    • +//
    +//
  • +//
  • \ref views +//
      +//
    • \ref views_subvectors
    • +//
    • \ref views_submatrices
    • +//
    • \ref views_rows
    • +//
    • \ref views_columns
    • +//
    +//
  • +//
  • \ref arithmetic_operations +//
      +//
    • \ref addition
    • +//
    • \ref subtraction
    • +//
    • \ref scalar_multiplication
    • +//
    • \ref vector_vector_multiplication +//
        +//
      • \ref componentwise_multiplication
      • +//
      • \ref inner_product
      • +//
      • \ref outer_product
      • +//
      • \ref cross_product
      • +//
      +//
    • +//
    • \ref vector_vector_division
    • +//
    • \ref matrix_vector_multiplication
    • +//
    • \ref matrix_matrix_multiplication
    • +//
    +//
  • +//
  • \ref custom_operations
  • +//
  • \ref shared_memory_parallelization +//
      +//
    • \ref openmp_parallelization
    • +//
    • \ref cpp_threads_parallelization
    • +//
    • \ref boost_threads_parallelization
    • +//
    • \ref serial_execution
    • +//
    +//
  • +//
  • \ref serialization +//
      +//
    • \ref vector_serialization
    • +//
    • \ref matrix_serialization
    • +//
    +//
  • +//
  • \ref blas_functions
  • +//
  • \ref lapack_functions
  • +//
  • \ref configuration_files
  • +//
  • \ref custom_data_types
  • +//
  • \ref error_reporting_customization
  • +//
  • \ref intra_statement_optimization
  • +//
+*/ +//************************************************************************************************* + + +//**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 +//
+// +// 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 +// (Intel MKL, +// ACML, +// Atlas, +// Goto, ...). 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 LAPACK. 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 +//
+// +// \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 ./blaze 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 ./blaze 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 +//
+// +// 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 ./blaze/config/ 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: +// +// - ./blaze/config/BLAS.h: 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. +// - ./blaze/config/CacheSize.h: 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. +// - ./blaze/config/Thresholds.h: 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 + #include + + using blaze::StaticVector; + using blaze::DynamicVector; + + // Instantiation of a static 3D column vector. The vector is directly initialized as + // ( 4 -2 5 ) + StaticVector a{ 4, -2, 5 }; + + // Instantiation of a dynamic 3D column vector. Via the subscript operator the values are set to + // ( 2 5 -3 ) + DynamicVector b( 3UL ); + b[0] = 2; + b[1] = 5; + b[2] = -3; + + // Adding the vectors a and b + DynamicVector 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 + + using namespace blaze; + + // Instantiating a dynamic 3D column vector + DynamicVector 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 A( 2UL, 3UL, 0 ); + A(0,0) = 1; + A(0,2) = 4; + A(1,1) = -2; + + // Performing a matrix/vector multiplication + DynamicVector 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 B{ { 3, -1 }, { 0, 2 }, { -1, 0 } }; + + // Performing a matrix/matrix multiplication + DynamicMatrix 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 A( NN, NN ); + blaze::DynamicVector 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 +// +// 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 a{ 1, 2, 3 }; + + // Setup of the 3-dimensional dense row vector + // + // ( 4 5 6 ) + // + DynamicVector 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 c( 3UL ); + \endcode + +// \n \section vectors_details Vector Details +//
+// +// - \ref vector_types +// - \ref vector_operations +// +// +// \n \section vectors_examples Examples +//
+ + \code + using blaze::StaticVector; + using blaze::DynamicVector; + using blaze::CompressedVector; + using blaze::rowVector; + using blaze::columnVector; + + StaticVector a; // Instantiation of a 6-dimensional static column vector + CompressedVector b; // Instantiation of a compressed row vector + DynamicVector c; // Instantiation of a dynamic column vector + + // ... Resizing and initialization + + c = a + trans( b ); + \endcode + +// \n Previous: \ref getting_started     Next: \ref vector_types +*/ +//************************************************************************************************* + + +//**Vector Types*********************************************************************************** +/*!\page vector_types Vector Types +// +// \tableofcontents +// +// +// \n \section vector_types_static_vector StaticVector +//
+// +// 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 + \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 a; + + // Definition of a 4-dimensional single precision column vector + blaze::StaticVector b; + + // Definition of a 6-dimensional double precision row vector + blaze::StaticVector c; + \endcode + +// \n \section vector_types_dynamic_vector DynamicVector +//
+// +// 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 + \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 a( 3UL ); + + // Definition of a 4-dimensional single precision column vector + blaze::DynamicVector b( 4UL ); + + // Definition of a double precision row vector with size 0 + blaze::DynamicVector c; + \endcode + +// \n \section vector_types_hybrid_vector HybridVector +//
+// +// 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 + \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 a( 3UL ); + + // Definition of a 4-dimensional single precision column vector with a maximum size of 16 + blaze::HybridVector b( 4UL ); + + // Definition of a double precision row vector with size 0 and a maximum size of 6 + blaze::HybridVector c; + \endcode + +// \n \section vector_types_custom_vector CustomVector +//
+// +// 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 + \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 UnalignedUnpadded; + std::vector vec( 7UL ); + UnalignedUnpadded a( &vec[0], 7UL ); + + // Definition of a managed custom column vector for unaligned but padded 'float' arrays + typedef CustomVector UnalignedPadded; + UnalignedPadded b( new float[16], 9UL, 16UL, blaze::ArrayDelete() ); + + // Definition of a managed custom row vector for aligned, unpadded 'double' arrays + typedef CustomVector AlignedUnpadded; + AlignedUnpadded c( blaze::allocate( 7UL ), 7UL, blaze::Deallocate() ); + + // Definition of a managed custom row vector for aligned, padded 'complex' arrays + typedef CustomVector,aligned,padded,columnVector> AlignedPadded; + AlignedPadded d( allocate< complex >( 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: +// +// -# \ref vector_types_custom_vector_memory_management +// -# \ref vector_types_custom_vector_copy_operations +// -# \ref vector_types_custom_vector_alignment +// -# \ref vector_types_custom_vector_padding +// +// \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 vec( 3UL ); + CustomVector 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 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 c( allocate( 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 CustomType; + + std::vector 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 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( 5UL ); // Needs to be 32-bit aligned + CustomVector 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 CustomType; + + // Creating padded custom vectors of size 3 and a capacity of 4 + CustomType a( allocate( 4UL ), 3UL, 4UL, Deallocate() ); + CustomType b( allocate( 4UL ), 3UL, 4UL, Deallocate() ); + CustomType c( allocate( 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 CustomType; + + // Creating unpadded custom vector of size 3 + CustomType a( allocate( 3UL ), 3UL, Deallocate() ); + CustomType b( allocate( 3UL ), 3UL, Deallocate() ); + CustomType c( allocate( 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 +//
+// +// 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 + \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 a( 3UL ); + + // Definition of a 4-dimensional single precision column vector with capacity for 3 non-zero elements + blaze::CompressedVector b( 4UL, 3UL ); + + // Definition of a double precision row vector with size 0 + blaze::CompressedVector c; + \endcode + +// \n Previous: \ref vectors     Next: \ref vector_operations +*/ +//************************************************************************************************* + + +//**Vector Operations****************************************************************************** +/*!\page vector_operations Vector Operations +// +// \tableofcontents +// +// +// \n \section vector_operations_constructors Constructors +//
+// +// 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 v1; // Instantiation of a 2D integer column vector. + // All elements are initialized to 0. + StaticVector v2; // Instantiation of a 3D long integer column vector. + // Again, all elements are initialized to 0L. + DynamicVector v3; // Instantiation of a dynamic single precision column + // vector of size 0. + DynamicVector v4; // Instantiation of a dynamic double precision row + // vector of size 0. + CompressedVector v5; // Instantiation of a compressed integer column + // vector of size 0. + CompressedVector 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 v7( 9UL ); // Instantiation of an integer dynamic column vector + // of size 9. The elements are NOT initialized! + HybridVector< complex, 5UL > v8( 2UL ); // Instantiation of a column vector with two single + // precision complex values. The elements are + // default constructed. + CompressedVector 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 v10( 2 ); // Instantiation of a 3D integer row vector. + // All elements are initialized to 2. + DynamicVector v11( 3UL, 7.0F ); // Instantiation of a dynamic single precision + // column vector of size 3. All elements are + // set to 7.0F. + CompressedVector 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 array1( new double[2] ); + // ... Initialization of the dynamic array + blaze::StaticVector v13( 2UL, array1.get() ); + + int array2[4] = { 4, -5, -6, 7 }; + blaze::StaticVector 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 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 v16( v7 ); // Instantiation of the dense column vector v16 + // as copy of the dense column vector v7. + DynamicVector v17( v9 ); // Instantiation of the dense row vector v17 as + // copy of the sparse row vector v9. + CompressedVector v18( v1 ); // Instantiation of the sparse column vector v18 + // as copy of the dense column vector v1. + CompressedVector 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 v23( v7 ); // Runtime error: Size does not match! + StaticVector v24( v10 ); // Compile time error: Size does not match! + \endcode + +// \n \section vector_operations_assignment Assignment +//
+// +// 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 v1; + blaze::DynamicVector 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 v1; + blaze::DynamicVector 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 v1; + blaze::DynamicVector 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 v1; + blaze::DynamicVector v2( 3UL ); + blaze::DynamicVector v3( 5UL ); + blaze::CompressedVector v4( 3UL ); + blaze::CompressedVector 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 v1; + blaze::DynamicVector v2( 5UL ); + blaze::CompressedVector v3( 7UL ); + blaze::DynamicVector v4( 7UL ); + blaze::CompressedVector 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 +//
+// +// 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 v1( 5UL ); + v1[0] = 1; + v1[1] = 3; + // ... + + blaze::CompressedVector 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 v1( 10UL ); + + for( size_t i=0UL; i v1( 10UL ); + + // ... Initialization of the vector + + // Traversing the vector by Iterator + for( CompressedVector::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::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::Iterator it=begin( v1 ); it!=end( v1 ); ++it ) { + // ... + } + + for( CompressedVector::ConstIterator it=cbegin( v1 ); it!=cend( v1 ); ++it ) { + // ... + } + \endcode + +// \n \section vector_operations_element_insertion Element Insertion +//
+// +// 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 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 +//
+// +// \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 v1( 10UL ); + v1.size(); // Returns 10 + + // Instantiating a compressed vector with size 12 and capacity for 3 non-zero elements + blaze::CompressedVector 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 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 v1; + CompressedVector 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 VectorType; + typedef blaze::Subvector 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 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 +//
+// +// \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 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 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 a; + // ... Resizing and initialization + if( isnan( a ) ) { ... } + \endcode + + \code + blaze::CompressedVector 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 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 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 a{ -5, 2, 7, 4 }; + blaze::StaticVector 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 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 a{ -1, 2, -3 }; + blaze::StaticVector 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 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 cplx; + + // Creating the vector + // ( (-2,-1) ) + // ( ( 1, 1) ) + StaticVector a{ cplx(-2.0,-1.0), cplx(1.0,1.0) }; + + // Computing the vector of complex conjugates + // ( (-2, 1) ) + // ( ( 1,-1) ) + StaticVector b; + b = conj( a ); + \endcode + +// Additionally, vectors can be conjugated in-place via the \c conjugate() function: + + \code + blaze::DynamicVector 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 cplx; + + // Creating the vector + // ( (-2,-1) ) + // ( ( 1, 1) ) + StaticVector a{ cplx(-2.0,-1.0), cplx(1.0,1.0) }; + + // Extracting the real part of each vector element + // ( -2 ) + // ( 1 ) + StaticVector 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 cplx; + + // Creating the vector + // ( (-2,-1) ) + // ( ( 1, 1) ) + StaticVector a{ cplx(-2.0,-1.0), cplx(1.0,1.0) }; + + // Extracting the imaginary part of each vector element + // ( -1 ) + // ( 1 ) + StaticVector 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 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 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 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 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 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 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 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 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 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 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 v1( 4UL ); + blaze::CompressedVector 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, rowVector > v1( 4UL ); + blaze::DynamicVector< complex, 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 v1( 10UL ); + blaze::CompressedVector 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 v1( 10UL ); + blaze::DynamicVector v2( 20UL ); + + swap( v1, v2 ); // Swapping the contents of v1 and v2 + \endcode + +// \n Previous: \ref vector_types     Next: \ref matrices +*/ +//************************************************************************************************* + + +//**Matrices*************************************************************************************** +/*!\page matrices Matrices +// +// \tableofcontents +// +// +// \n \section matrices_general General Concepts +//
+// +// 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 A{ { 1, 2, 3 }, + { 4, 5, 6 } }; + + // Setup of the 3x2 column-major dense matrix + // + // ( 1 4 ) + // ( 2 5 ) + // ( 3 6 ) + // + DynamicMatrix 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 C( 3UL, 3UL ); + \endcode + +// \n \section matrices_details Matrix Details +//
+// +// - \ref matrix_types +// - \ref matrix_operations +// +// +// \n \section matrices_examples Examples +//
+ + \code + using blaze::StaticMatrix; + using blaze::DynamicMatrix; + using blaze::CompressedMatrix; + using blaze::rowMajor; + using blaze::columnMajor; + + StaticMatrix A; // Instantiation of a 6x20 row-major static matrix + CompressedMatrix B; // Instantiation of a row-major compressed matrix + DynamicMatrix C; // Instantiation of a column-major dynamic matrix + + // ... Resizing and initialization + + C = A * B; + \endcode + +// \n Previous: \ref vector_operations     Next: \ref matrix_types +*/ +//************************************************************************************************* + + +//**Matrix Types*********************************************************************************** +/*!\page matrix_types Matrix Types +// +// \tableofcontents +// +// +// \n \section matrix_types_static_matrix StaticMatrix +//
+// +// 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 + \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 A; + + // Definition of a 4x6 single precision row-major matrix + blaze::StaticMatrix B; + + // Definition of a 6x4 double precision column-major matrix + blaze::StaticMatrix C; + \endcode + +// \n \section matrix_types_dynamic_matrix DynamicMatrix +//
+// +// 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 + \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 A( 3UL, 4UL ); + + // Definition of a 4x6 single precision row-major matrix + blaze::DynamicMatrix B( 4UL, 6UL ); + + // Definition of a double precision column-major matrix with 0 rows and columns + blaze::DynamicMatrix C; + \endcode + +// \n \section matrix_types_hybrid_matrix HybridMatrix +//
+// +// 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 + \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 A( 3UL, 4UL ); + + // Definition of a 4x6 single precision row-major matrix with maximum dimensions of 12x16 + blaze::HybridMatrix B( 4UL, 6UL ); + + // Definition of a 0x0 double precision column-major matrix and maximum dimensions of 6x6 + blaze::HybridMatrix C; + \endcode + +// \n \section matrix_types_custom_matrix CustomMatrix +//
+// +// 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 + \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 UnalignedUnpadded; + std::vector vec( 12UL ) + UnalignedUnpadded A( &vec[0], 3UL, 4UL ); + + // Definition of a managed 5x6 custom matrix for unaligned but padded 'float' arrays + typedef CustomMatrix 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 AlignedUnpadded; + AlignedUnpadded C( blaze::allocate( 192UL ), 12UL, 13UL, 16UL, blaze::Deallocate ); + + // Definition of a 7x14 custom matrix for aligned, padded 'complex' arrays + typedef CustomMatrix,aligned,padded,columnMajor> AlignedPadded; + AlignedPadded D( blaze::allocate( 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: +// +// -# \ref matrix_types_custom_matrix_memory_management +// -# \ref matrix_types_custom_matrix_copy_operations +// -# \ref matrix_types_custom_matrix_alignment +// -# \ref matrix_types_custom_matrix_padding +// +// \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 vec( 12UL ); + CustomMatrix 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 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 C( allocate( 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 CustomType; + + std::vector 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 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( 40UL ); // Is guaranteed to be 32-bit aligned + CustomMatrix 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 CustomType; + + // Creating padded custom 3x3 matrix with an additional padding element in each row + CustomType A( allocate( 12UL ), 3UL, 3UL, 4UL, Deallocate() ); + CustomType B( allocate( 12UL ), 3UL, 3UL, 4UL, Deallocate() ); + CustomType C( allocate( 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 CustomType; + + // Creating unpadded custom 3x3 matrix + CustomType A( allocate( 12UL ), 3UL, 3UL, 4UL, Deallocate() ); + CustomType B( allocate( 12UL ), 3UL, 3UL, 4UL, Deallocate() ); + CustomType C( allocate( 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 +//
+// +// 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 + \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 A( 3UL, 4UL ); + + // Definition of a 4x6 single precision row-major matrix + blaze::CompressedMatrix B( 4UL, 6UL ); + + // Definition of a double precision column-major matrix with 0 rows and columns + blaze::CompressedMatrix C; + \endcode + +// \n Previous: \ref matrices     Next: \ref matrix_operations +*/ +//************************************************************************************************* + + +//**Matrix Operations****************************************************************************** +/*!\page matrix_operations Matrix Operations +// +// \tableofcontents +// +// +// \n \section matrix_operations_constructors Constructors +//
+// +// 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 M1; // Instantiation of a 2x2 integer row-major + // matrix. All elements are initialized to 0. + DynamicMatrix M2; // Instantiation of a single precision dynamic + // row-major matrix with 0 rows and 0 columns. + DynamicMatrix M3; // Instantiation of a double precision dynamic + // column-major matrix with 0 rows and 0 columns. + CompressedMatrix M4; // Instantiation of a compressed integer + // row-major matrix of size 0x0. + CompressedMatrix 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 M6( 5UL, 4UL ); // Instantiation of a 5x4 dynamic row-major + // matrix. The elements are not initialized. + HybridMatrix M7( 3UL, 7UL ); // Instantiation of a 3x7 hybrid row-major + // matrix. The elements are not initialized. + CompressedMatrix 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 M9( 7 ); // Instantiation of a 4x3 integer column-major + // matrix. All elements are initialized to 7. + DynamicMatrix M10( 2UL, 5UL, 2.0F ); // Instantiation of a 2x5 single precision row-major + // matrix. All elements are initialized to 2.0F. + CompressedMatrix 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 array1( new double[6] ); + // ... Initialization of the dynamic array + blaze::StaticMatrix M12( 2UL, 3UL, array1.get() ); + + int array2[2][2] = { { 4, -5 }, { -6, 7 } }; + blaze::StaticMatrix 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 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 M15( M6 ); // Instantiation of the dense row-major matrix M15 + // as copy of the dense row-major matrix M6. + DynamicMatrix M16( M8 ); // Instantiation of the dense column-major matrix M16 + // as copy of the sparse column-major matrix M8. + CompressedMatrix M17( M7 ); // Instantiation of the compressed column-major matrix + // M17 as copy of the dense row-major matrix M7. + CompressedMatrix 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 M19( M6 ); // Runtime error: Number of rows and columns + // does not match! + StaticMatrix M20( M9 ); // Compile time error: Number of columns does + // not match! + \endcode + +// \n \section matrix_operations_assignment Assignment +//
+// +// 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 M1; + blaze::DynamicMatrix 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 M1; + blaze::StaticMatrix M2; + blaze::DynamicMatrix 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 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 M1; + blaze::DynamicMatrix M2( 3UL, 2UL ); + blaze::DynamicMatrix M3( 5UL, 2UL ); + blaze::CompressedMatrix M4( 3UL, 2UL ); + blaze::CompressedMatrix 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 M1; + blaze::DynamicMatrix M2( 2UL, 3UL ); + blaze::CompressedMatrix M3( 2UL, 3UL ); + blaze::CompressedMatrix M4( 2UL, 4UL ); + blaze::StaticMatrix M5; + blaze::CompressedMatrix 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 +//
+// +// 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 M1( 4UL, 6UL ); + M1(0,0) = 1; + M1(0,1) = 3; + // ... + + blaze::CompressedMatrix 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 M1( 4UL, 4UL ); + + for( size_t i=0UL; i M1( 4UL, 6UL ); + + // Traversing the matrix by Iterator + for( size_t i=0UL; i::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::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::Iterator it=begin( A, i ); it!=end( A, i ); ++it ) { + // ... + } + } + + for( size_t i=0UL; i::ConstIterator it=cbegin( A, i ); it!=cend( A, i ); ++it ) { + // ... + } + } + \endcode + +// \n \section matrix_operations_element_insertion Element Insertion +//
+// +// 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 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 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 +//
+// +// \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 M1( 10UL, 8UL ); + M1.rows(); // Returns 10 + + // Instantiating a compressed matrix with 8 rows and 12 columns + blaze::CompressedMatrix 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 M1( 6UL, 8UL ); + M1.columns(); // Returns 8 + + // Instantiating a compressed matrix with 8 rows and 7 columns + blaze::CompressedMatrix 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 M1( 5UL, 7UL ); + blaze::StaticMatrix 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 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 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 M1; + CompressedMatrix 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 MatrixType; + typedef blaze::Row 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 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 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 +//
+// +// \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 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 M1( 7UL, 6UL, 5 ); // Setup of a row-major matrix + blaze::DynamicMatrix 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 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 A( 3UL, 4UL ); + // ... Initialization + if( isnan( A ) ) { ... } + \endcode + + \code + blaze::CompressedMatrix 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 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 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 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 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 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 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 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 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 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 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 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 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 A{ { -5, 2, 7 }, + { 4, 0, 1 } }; + blaze::StaticMatrix 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 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 A{ { -1, 2, -3 }, + { 4, -5, 6 } }; + blaze::StaticMatrix 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 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 cplx; + + // Creating the matrix + // ( (1,0) (-2,-1) ) + // ( (1,1) ( 0, 1) ) + StaticMatrix 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 B; + B = conj( A ); + \endcode + +// Additionally, matrices can be conjugated in-place via the \c conjugate() function: + + \code + blaze::DynamicMatrix 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 cplx; + + // Creating the matrix + // ( (1,0) (-2,-1) ) + // ( (1,1) ( 0, 1) ) + StaticMatrix 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 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 cplx; + + // Creating the matrix + // ( (1,0) (-2,-1) ) + // ( (1,1) ( 0, 1) ) + StaticMatrix 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 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 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 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 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 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 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 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 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 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 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 M1( 5UL, 2UL ); + blaze::CompressedMatrix 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 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, rowMajor > M1( 5UL, 2UL ); + blaze::CompressedMatrix< complex, 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 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 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 or \c complex 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 M1( 10UL, 15UL ); + blaze::DynamicMatrix M2( 20UL, 10UL ); + + swap( M1, M2 ); // Swapping the contents of M1 and M2 + \endcode + +// \n \section matrix_operations_matrix_inversion Matrix Inversion +//
+// +// The inverse of a square dense matrix can be computed via the \c inv() function: + + \code + blaze::DynamicMatrix 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 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( A ); + + // In-place inversion of a symmetric indefinite matrix by means of a Bunch-Kaufman decomposition + invert( A ); + + // In-place inversion of a Hermitian indefinite matrix by means of a Bunch-Kaufman decomposition + invert( A ); + + // In-place inversion of a positive definite matrix by means of a Cholesky decomposition + invert( 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 or \c complex 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 +//
+// +// \note All decomposition functions can only be used for dense matrices with \c float, \c double, +// \c complex or \c complex 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 A; + // ... Resizing and initialization + + blaze::DynamicMatrix L, U, P; + + lu( A, L, U, P ); // LU decomposition of a row-major matrix + + assert( A == L * U * P ); + \endcode + + \code + blaze::DynamicMatrix A; + // ... Resizing and initialization + + blaze::DynamicMatrix 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 > A; + // ... Resizing and initialization + + blaze::LowerMatrix< blaze::DynamicMatrix > L; + blaze::UpperMatrix< blaze::DynamicMatrix > U; + blaze::DynamicMatrix 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 A; + // ... Resizing and initialization + + blaze::DynamicMatrix 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 > A; + // ... Resizing and initialization + + blaze::LowerMatrix< blaze::DynamicMatrix > 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 A; + // ... Resizing and initialization + + blaze::DynamicMatrix Q; + blaze::DynamicMatrix 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 > A; + // ... Resizing and initialization + + blaze::DynamicMatrix Q; + blaze::UpperMatrix< blaze::DynamicMatrix > 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 A; + // ... Resizing and initialization + + blaze::DynamicMatrix R; + blaze::DynamicMatrix 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,blaze::columnMajor> > A; + // ... Resizing and initialization + + blaze::UpperMatrix< blaze::DynamicMatrix,blaze::columnMajor> > R; + blaze::DynamicMatrix,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 A; + // ... Resizing and initialization + + blaze::DynamicMatrix Q; + blaze::DynamicMatrix 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 > A; + // ... Resizing and initialization + + blaze::DynamicMatrix Q; + blaze::LowerMatrix< blaze::DynamicMatrix > 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 A; + // ... Resizing and initialization + + blaze::DynamicMatrix L; + blaze::DynamicMatrix 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,blaze::columnMajor> > A; + // ... Resizing and initialization + + blaze::LowerMatrix< blaze::DynamicMatrix,blaze::columnMajor> > L; + blaze::DynamicMatrix,blaze::rowMajor> Q; + + lq( A, L, Q ); // LQ decomposition of A + \endcode + +// \n Previous: \ref matrix_types     Next: \ref adaptors +*/ +//************************************************************************************************* + + +//**Adaptors*************************************************************************************** +/*!\page adaptors Adaptors +// +// \tableofcontents +// +// +// \section adaptors_general General Concepts +//
+// +// 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: +// +//
    +//
  • \ref adaptors_symmetric_matrices
  • +//
  • \ref adaptors_hermitian_matrices
  • +//
  • \ref adaptors_triangular_matrices +//
      +//
    • \ref adaptors_triangular_matrices "Lower Triangular Matrices" +//
        +//
      • \ref adaptors_triangular_matrices_lowermatrix
      • +//
      • \ref adaptors_triangular_matrices_unilowermatrix
      • +//
      • \ref adaptors_triangular_matrices_strictlylowermatrix
      • +//
      +//
    • +//
    • \ref adaptors_triangular_matrices "Upper Triangular Matrices" +//
        +//
      • \ref adaptors_triangular_matrices_uppermatrix
      • +//
      • \ref adaptors_triangular_matrices_uniuppermatrix
      • +//
      • \ref adaptors_triangular_matrices_strictlyuppermatrix
      • +//
      +//
    • +//
    • \ref adaptors_triangular_matrices "Diagonal Matrices" +//
        +//
      • \ref adaptors_triangular_matrices_diagonalmatrix
      • +//
      +//
    • +//
    +//
  • +//
+// +// 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 +//
+// +// 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 > A; + LowerMatrix< DynamicMatrix > B; + DynamicMatrix 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 > A; + CompressedVector x; + DynamicVector 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     Next: \ref adaptors_symmetric_matrices +*/ +//************************************************************************************************* + + +//**Symmetric Matrices***************************************************************************** +/*!\page adaptors_symmetric_matrices Symmetric Matrices +// +// \tableofcontents +// +// +// \n \section adaptors_symmetric_matrices_general Symmetric Matrices +//
+// +// 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 +//
+// +// 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 + \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 > A; + + // Definition of a resizable column-major dense symmetric matrix based on HybridMatrix + blaze::SymmetricMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense symmetric matrix based on DynamicMatrix + blaze::SymmetricMatrix< blaze::DynamicMatrix > C; + + // Definition of a fixed size row-major dense symmetric matrix based on CustomMatrix + blaze::SymmetricMatrix< blaze::CustomMatrix > D; + + // Definition of a compressed row-major single precision symmetric matrix + blaze::SymmetricMatrix< blaze::CompressedMatrix > 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 +//
+// +// 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: +// +// -# \ref adaptors_symmetric_matrices_square +// -# \ref adaptors_symmetric_matrices_symmetry +// -# \ref adaptors_symmetric_matrices_initialization +// +// \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 > 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 > A; + + // Compilation error: the provided matrix type is not a square matrix type + SymmetricMatrix< StaticMatrix > 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 > 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 B{ { 3.0, 8.0, -2.0 }, + { 8.0, 0.0, -1.0 }, + { -2.0, -1.0, 4.0 } }; + + SymmetricMatrix< DynamicMatrix > C( B ); // OK + + // Assignment of a non-symmetric dense matrix + StaticMatrix 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 > 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 > 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 > 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 > A1( 4 ), A2( 4 ); + + // Setup of the 3x2 dynamic matrix + // + // ( 1 2 ) + // B = ( 3 4 ) + // ( 5 6 ) + // + DynamicMatrix 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 A( 5, 5 ); + + // Default initialized, 5x5 row-major symmetric dynamic matrix + SymmetricMatrix< DynamicMatrix > B( 5 ); + \endcode + +// \n \section adaptors_symmetric_matrices_arithmetic_operations Arithmetic Operations +//
+// +// 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 E( 3, 3 ); // Empty row-major sparse single precision 3x3 matrix + + SymmetricMatrix< HybridMatrix > F; + SymmetricMatrix< StaticMatrix > 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 +//
+// +// 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 > > 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{ { 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 +//
+// +// 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 > A; + SymmetricMatrix< CompressedMatrix > B; + DynamicMatrix 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 > A; + CompressedVector x; + DynamicVector 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 > DynamicSymmetric; + + DynamicSymmetric A( 10UL ); + Row 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 > A, C; + DynamicMatrix 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 > 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     Next: \ref adaptors_hermitian_matrices +*/ +//************************************************************************************************* + + +//**Hermitian Matrices***************************************************************************** +/*!\page adaptors_hermitian_matrices Hermitian Matrices +// +// \tableofcontents +// +// +// \n \section adaptors_hermitian_matrices_general Hermitian Matrices +//
+// +// 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 +//
+// +// 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 + \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 > A; + + // Definition of a resizable column-major dense Hermitian matrix based on HybridMatrix + blaze::HermitianMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense Hermitian matrix based on DynamicMatrix + blaze::HermitianMatrix< blaze::DynamicMatrix,rowMajor> > C; + + // Definition of a fixed size row-major dense Hermitian matrix based on CustomMatrix + blaze::HermitianMatrix< blaze::CustomMatrix > D; + + // Definition of a compressed row-major single precision complex Hermitian matrix + blaze::HermitianMatrix< blaze::CompressedMatrix,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 > A; // Both Hermitian and symmetric + SymmetricMatrix< DynamicMatrix > B; // Both Hermitian and symmetric + + // The following two matrices will behave differently + HermitianMatrix< DynamicMatrix< complex > > C; // Only Hermitian + SymmetricMatrix< DynamicMatrix< complex > > D; // Only symmetric + + // Block-structured Hermitian matrices are not allowed + HermitianMatrix< DynamicMatrix< DynamicVector > > E; // Compilation error! + SymmetricMatrix< DynamicMatrix< DynamicVector > > F; // Block-structured symmetric matrix + \endcode + +// \n \section adaptors_hermitian_matrices_special_properties Special Properties of Hermitian Matrices +//
+// +// 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: +// +// -# \ref adaptors_hermitian_matrices_square +// -# \ref adaptors_hermitian_matrices_hermitian +// -# \ref adaptors_hermitian_matrices_initialization +// +// \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,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,3UL,3UL,columnMajor> > A; + + // Compilation error: the provided matrix type is not a square matrix type + HermitianMatrix< StaticMatrix,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 cplx; + + // Default constructed, row-major 3x3 Hermitian compressed matrix + HermitianMatrix< CompressedMatrix > 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 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 > C( B ); // OK + + // Assignment of a non-Hermitian dense matrix + StaticMatrix 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 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 > 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 > 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 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 > 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 cplx; + + // Setup of two default 4x4 Hermitian matrices + HermitianMatrix< DynamicMatrix > A1( 4 ), A2( 4 ); + + // Setup of the 3x2 dynamic matrix + // + // ( (1,-1) (2, 5) ) + // B = ( (3, 0) (4,-6) ) + // ( (5, 0) (6, 0) ) + // + DynamicMatrix 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 A( 5, 5 ); + + // Default initialized, 5x5 row-major Hermitian dynamic matrix + HermitianMatrix< DynamicMatrix > B( 5 ); + \endcode + +// \n \section adaptors_hermitian_matrices_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 cplx; + + DynamicMatrix A( 3, 3 ); + CompressedMatrix B( 3, 3 ); + + HermitianMatrix< DynamicMatrix > C( 3 ); + HermitianMatrix< CompressedMatrix > D( 3 ); + + HermitianMatrix< HybridMatrix > E; + HermitianMatrix< StaticMatrix > 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 +//
+// +// 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 > A; // Both Hermitian and symmetric + HermitianMatrix< CompressedMatrix > B; // Both Hermitian and symmetric + DynamicMatrix 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 > A; // Hermitian and symmetric + CompressedVector x; + DynamicVector 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 > DynamicHermitian; + + DynamicHermitian A( 10UL ); // Both Hermitian and symmetric + Row 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 > > A, C; + DynamicMatrix 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 > 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     Next: \ref adaptors_triangular_matrices +*/ +//************************************************************************************************* + + +//**Triangular Matrices**************************************************************************** +/*!\page adaptors_triangular_matrices Triangular Matrices +// +// \tableofcontents +// +// +// \n \section adaptors_triangular_matrices_general Triangular Matrices +//
+// +// 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: +// - \ref adaptors_triangular_matrices_lowermatrix +// - \ref adaptors_triangular_matrices_unilowermatrix +// - \ref adaptors_triangular_matrices_strictlylowermatrix +// +// Upper triangular matrices: +// - \ref adaptors_triangular_matrices_uppermatrix +// - \ref adaptors_triangular_matrices_uniuppermatrix +// - \ref adaptors_triangular_matrices_strictlyuppermatrix +// +// Diagonal matrices +// - \ref adaptors_triangular_matrices_diagonalmatrix +// +// +// \n \section adaptors_triangular_matrices_lowermatrix LowerMatrix +//
+// +// 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 + \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 > A; + + // Definition of a resizable column-major dense lower matrix based on HybridMatrix + blaze::LowerMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense lower matrix based on DynamicMatrix + blaze::LowerMatrix< blaze::DynamicMatrix > C; + + // Definition of a fixed size row-major dense lower matrix based on CustomMatrix + blaze::LowerMatrix< blaze::CustomMatrix > D; + + // Definition of a compressed row-major single precision lower matrix + blaze::LowerMatrix< blaze::CompressedMatrix > 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 +//
+// +// 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 + \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 > A; + + // Definition of a resizable column-major dense unilower matrix based on HybridMatrix + blaze::UniLowerMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense unilower matrix based on DynamicMatrix + blaze::UniLowerMatrix< blaze::DynamicMatrix > C; + + // Definition of a compressed row-major single precision unilower matrix + blaze::UniLowerMatrix< blaze::CompressedMatrix > 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 +//
+// +// 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 + \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 > A; + + // Definition of a resizable column-major dense strictly lower matrix based on HybridMatrix + blaze::StrictlyLowerMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense strictly lower matrix based on DynamicMatrix + blaze::StrictlyLowerMatrix< blaze::DynamicMatrix > C; + + // Definition of a compressed row-major single precision strictly lower matrix + blaze::StrictlyLowerMatrix< blaze::CompressedMatrix > 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 +//
+// +// 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 + \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 > A; + + // Definition of a resizable column-major dense upper matrix based on HybridMatrix + blaze::UpperMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense upper matrix based on DynamicMatrix + blaze::UpperMatrix< blaze::DynamicMatrix > C; + + // Definition of a compressed row-major single precision upper matrix + blaze::UpperMatrix< blaze::CompressedMatrix > 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 +//
+// +// 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 + \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 > A; + + // Definition of a resizable column-major dense uniupper matrix based on HybridMatrix + blaze::UniUpperMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense uniupper matrix based on DynamicMatrix + blaze::UniUpperMatrix< blaze::DynamicMatrix > C; + + // Definition of a compressed row-major single precision uniupper matrix + blaze::UniUpperMatrix< blaze::CompressedMatrix > 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 +//
+// +// 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 + \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 > A; + + // Definition of a resizable column-major dense strictly upper matrix based on HybridMatrix + blaze::StrictlyUpperMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense strictly upper matrix based on DynamicMatrix + blaze::StrictlyUpperMatrix< blaze::DynamicMatrix > C; + + // Definition of a compressed row-major single precision strictly upper matrix + blaze::StrictlyUpperMatrix< blaze::CompressedMatrix > 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 +//
+// +// 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 + \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 > A; + + // Definition of a resizable column-major dense diagonal matrix based on HybridMatrix + blaze::DiagonalMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense diagonal matrix based on DynamicMatrix + blaze::DiagonalMatrix< blaze::DynamicMatrix > C; + + // Definition of a compressed row-major single precision diagonal matrix + blaze::DiagonalMatrix< blaze::CompressedMatrix > 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 +//
+// +// 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: +// +// -# \ref adaptors_triangular_matrices_square +// -# \ref adaptors_triangular_matrices_triangular +// -# \ref adaptors_triangular_matrices_initialization +// -# \ref adaptors_triangular_matrices_storage +// -# \ref adaptors_triangular_matrices_scaling +// +// \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 > 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 > A; + + // Compilation error: the provided matrix type is not a square matrix type + LowerMatrix< StaticMatrix > 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 > 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 B{ { 3.0, 0.0, 0.0 }, + { 8.0, 0.0, 0.0 }, + { -2.0, -1.0, 4.0 } }; + + LowerMatrix< DynamicMatrix > C( B ); // OK + + // Assignment of a non-lower dense matrix + StaticMatrix 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 > 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 > 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 > A1( 4 ), A2( 4 ); + + // Setup of a 4-dimensional vector + // + // v = ( 1 2 3 0 ) + // + DynamicVector 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 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 A( 5, 5 ); + + // 5x5 row-major lower dynamic matrix with default initialized upper matrix + LowerMatrix< DynamicMatrix > B( 5 ); + + // 7x7 column-major upper dynamic matrix with default initialized lower matrix + UpperMatrix< DynamicMatrix > C( 7 ); + + // 3x3 row-major diagonal dynamic matrix with default initialized lower and upper matrix + DiagonalMatrix< DynamicMatrix > 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 > SmallDiagonalMatrix; + + // Recommendation 2: use sparse matrices for large diagonal matrices + typedef blaze::DiagonalMatrix< blaze::CompressedMatrix > 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 > 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 +//
+// +// 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 A( 3, 3 ); + CompressedMatrix B( 3, 3 ); + + LowerMatrix< DynamicMatrix > C( 3 ); + UpperMatrix< CompressedMatrix > D( 3 ); + + LowerMatrix< HybridMatrix > E; + UpperMatrix< StaticMatrix > 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 +//
+// +// 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 > > A( 5 ); + + // Definition of a 7x7 block-structured upper matrix based on CompressedMatrix + UpperMatrix< CompressedMatrix< StaticMatrix > > 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 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 > > A( 5 ); + + // Compilation error: upper unitriangular matrices are restricted to numeric element types + UniUpperMatrix< CompressedMatrix< StaticMatrix > > B( 7 ); + \endcode + +// \n \section adaptors_triangular_matrices_performance Performance Considerations +//
+// +// 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 > A; + LowerMatrix< DynamicMatrix > B; + DynamicMatrix 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 > A; + DynamicVector 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 > A, C; + DynamicMatrix 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 > 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 > 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     Next: \ref views +*/ +//************************************************************************************************* + + +//**Views****************************************************************************************** +/*!\page views Views +// +// \tableofcontents +// +// +// \section views_general General Concepts +//
+// +// 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 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 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     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 +//
+// +// 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 + \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 +//
+// +// 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 DenseVectorType; + typedef blaze::CompressedVector 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 dsv = subvector( d1, 0UL, 10UL ); + + // Creating a view on the second ten elements of the sparse vector s1 + blaze::Subvector 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 +//
+// +// 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 VectorType; + typedef blaze::Subvector 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 +//
+// +// The elements of a subvector can be directly accessed via the subscript operator: + + \code + typedef blaze::DynamicVector VectorType; + VectorType v; + // ... Resizing and initialization + + // Creating an 8-dimensional subvector, starting from index 4 + blaze::Subvector 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 VectorType; + VectorType v; + // ... Resizing and initialization + + // Creating an 8-dimensional subvector, starting from index 4 + blaze::Subvector 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 VectorType; + typedef blaze::Subvector 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 VectorType; + typedef blaze::Subvector 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 +//
+// +// Inserting/accessing elements in a sparse subvector can be done by several alternative functions. +// The following example demonstrates all options: + + \code + typedef blaze::CompressedVector VectorType; + VectorType v( 256UL ); // Non-initialized vector of size 256 + + typedef blaze::Subvector 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 +//
+// +// 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 DenseVectorType; + typedef blaze::CompressedVector SparseVectorType; + DenseVectorType d1, d2, d3; + SparseVectorType s1, s2; + + // ... Resizing and initialization + + typedef blaze::DynamicMatrix DenseMatrixType; + DenseMatrixType A; + + typedef blaze::Subvector 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 +//
+// +// 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 DenseVectorType; + + DenseVectorType x; + // ... Resizing and initialization + + // Identical creations of an unaligned subvector in the range [8..23] + blaze::Subvector sv1 = subvector ( x, 8UL, 16UL ); + blaze::Subvector sv2 = subvector( x, 8UL, 16UL ); + blaze::Subvector sv3 = subvector ( x, 8UL, 16UL ); + blaze::Subvector sv4 = subvector( 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 sv = subvector( 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 VectorType; + typedef blaze::Subvector SubvectorType; + + VectorType d( 17UL ); + // ... Resizing and initialization + + // OK: Starts at the beginning, i.e. the first element is aligned + SubvectorType dsv1 = subvector( d, 0UL, 13UL ); + + // OK: Start index is a multiple of 4, i.e. the first element is aligned + SubvectorType dsv2 = subvector( d, 4UL, 7UL ); + + // OK: The start index is a multiple of 4 and the subvector includes the last element + SubvectorType dsv3 = subvector( d, 8UL, 9UL ); + + // Error: Start index is not a multiple of 4, i.e. the first element is not aligned + SubvectorType dsv4 = subvector( 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 SparseVectorType; + + SparseVectorType x; + // ... Resizing and initialization + + // Creating an aligned subvector in the range [8..23] + blaze::Subvector sv = subvector( x, 8UL, 16UL ); + \endcode + +// \n \section views_subvectors_on_subvectors 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, not a nested subvector type, since the view on a subvector +// is just another view on the underlying vector: + + \code + typedef blaze::DynamicVector VectorType; + typedef blaze::Subvector 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     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 +//
+// +// 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 + \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 +//
+// +// 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 DenseMatrixType; + typedef blaze::CompressedVector 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 dsm = submatrix( D1, 0UL, 0UL, 8UL, 16UL ); + + // Creating a view on the second 8x16 block of the sparse matrix S1 + blaze::Submatrix 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 +//
+// +// 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 MatrixType; + typedef blaze::Submatrix 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 +//
+// +// The elements of a submatrix can be directly accessed with the function call operator: + + \code + typedef blaze::DynamicMatrix MatrixType; + MatrixType A; + // ... Resizing and initialization + + // Creating a 8x8 submatrix, starting from position (4,4) + blaze::Submatrix 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 MatrixType; + MatrixType A; + // ... Resizing and initialization + + // Creating a 8x8 submatrix, starting from position (4,4) + blaze::Submatrix 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 MatrixType; + typedef blaze::Submatrix 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 MatrixType; + typedef blaze::Submatrix 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 +//
+// +// Inserting/accessing elements in a sparse submatrix can be done by several alternative functions. +// The following example demonstrates all options: + + \code + typedef blaze::CompressedMatrix MatrixType; + MatrixType A( 256UL, 512UL ); // Non-initialized matrix of size 256x512 + + typedef blaze::Submatrix 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 +//
+// +// 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 DenseMatrixType; + typedef blaze::CompressedMatrix SparseMatrixType; + DenseMatrixType D1, D2, D3; + SparseMatrixType S1, S2; + + typedef blaze::CompressedVector SparseVectorType; + SparseVectorType a, b; + + // ... Resizing and initialization + + typedef Submatrix 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 +//
+// +// 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 DenseMatrixType; + + DenseMatrixType A; + // ... Resizing and initialization + + // Identical creations of an unaligned submatrix of size 8x8, starting in row 0 and column 0 + blaze::Submatrix sm1 = submatrix ( A, 0UL, 0UL, 8UL, 8UL ); + blaze::Submatrix sm2 = submatrix( A, 0UL, 0UL, 8UL, 8UL ); + blaze::Submatrix sm3 = submatrix ( A, 0UL, 0UL, 8UL, 8UL ); + blaze::Submatrix sm4 = submatrix( 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 sv = submatrix( 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 MatrixType; + typedef blaze::Submatrix 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( 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( 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( 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( 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 SparseMatrixType; + + SparseMatrixType A; + // ... Resizing and initialization + + // Creating an aligned submatrix of size 8x8, starting in row 0 and column 0 + blaze::Submatrix sv = submatrix( A, 0UL, 0UL, 8UL, 8UL ); + \endcode + +// \n \section views_submatrices_on_submatrices Submatrices on Submatrices +//
+// +// 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 MatrixType; + typedef blaze::Submatrix 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 > 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 > A1( 4 ), A2( 4 ); + + // Setup of the 3x2 dynamic matrix + // + // ( 1 2 ) + // B = ( 3 4 ) + // ( 5 6 ) + // + DynamicMatrix 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     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 +//
+// +// 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 + \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 +//
+// +// 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 DenseVectorType; + typedef blaze::CompressedVector SparseVectorType; + typedef blaze::DynamicMatrix DenseMatrixType; + typedef blaze::CompressedMatrix 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 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 +//
+// +// 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 MatrixType; + typedef blaze::Row 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 +//
+// +// 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 MatrixType; + typedef blaze::Row 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 MatrixType; + typedef blaze::Row 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 +//
+// +// Inserting/accessing elements in a sparse row can be done by several alternative functions. +// The following example demonstrates all options: + + \code + typedef blaze::CompressedMatrix MatrixType; + MatrixType A( 10UL, 100UL ); // Non-initialized 10x100 matrix + + typedef blaze::Row 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 +//
+// +// 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 a( 2UL, 2.0 ), b; + blaze::CompressedVector c( 2UL ); + c[1] = 3.0; + + typedef blaze::DynamicMatrix DenseMatrix; + DenseMatrix A( 4UL, 2UL ); // Non-initialized 4x2 matrix + + typedef blaze::Row 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 +//
+// +// 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 MatrixType; + typedef blaze::Row 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 A( 128UL, 128UL ); + CompressedMatrix B( 128UL, 128UL ); + // ... Resizing and initialization + + // The computation of the 15th row of the multiplication between A and B ... + CompressedVector 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 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     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 +//
+// +// 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 + \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 +//
+// +// 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 DenseVectorType; + typedef blaze::CompressedVector SparseVectorType; + typedef blaze::DynamicMatrix DenseMatrixType; + typedef blaze::CompressedMatrix 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 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 +//
+// +// 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 MatrixType; + typedef blaze::Column 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 +//
+// +// 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 MatrixType; + typedef blaze::Column 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 MatrixType; + typedef blaze::Column 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 +//
+// +// Inserting/accessing elements in a sparse column can be done by several alternative functions. +// The following example demonstrates all options: + + \code + typedef blaze::CompressedMatrix MatrixType; + MatrixType A( 100UL, 10UL ); // Non-initialized 10x100 matrix + + typedef blaze::Column 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 +//
+// +// 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 a( 2UL, 2.0 ), b; + blaze::CompressedVector c( 2UL ); + c[1] = 3.0; + + typedef blaze::DynamicMatrix MatrixType; + MatrixType A( 2UL, 4UL ); // Non-initialized 2x4 matrix + + typedef blaze::Column 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 +//
+// +// 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 MatrixType; + typedef blaze::Column 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 A( 128UL, 128UL ); + CompressedMatrix B( 128UL, 128UL ); + // ... Resizing and initialization + + // The computation of the 15th column of the multiplication between A and B ... + CompressedVector 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 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     Next: \ref arithmetic_operations +*/ +//************************************************************************************************* + + +//**Arithmetic Operations************************************************************************** +/*!\page arithmetic_operations Arithmetic Operations +// +// \tableofcontents +// +// +// \b Blaze provides the following arithmetic operations for vectors and matrices: +// +//
    +//
  • \ref addition
  • +//
  • \ref subtraction
  • +//
  • \ref scalar_multiplication
  • +//
  • \ref vector_vector_multiplication +//
      +//
    • \ref componentwise_multiplication
    • +//
    • \ref inner_product
    • +//
    • \ref outer_product
    • +//
    • \ref cross_product
    • +//
    +//
  • +//
  • \ref vector_vector_division
  • +//
  • \ref matrix_vector_multiplication
  • +//
  • \ref matrix_matrix_multiplication
  • +//
+// +// \n Previous: \ref views_columns     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 v1( 5UL ), v3; + blaze::CompressedVector v2( 5UL ); + + // ... Initializing the vectors + + v3 = v1 + v2; // Addition of a two column vectors of different data type + \endcode + + \code + blaze::DynamicMatrix M1( 7UL, 3UL ); + blaze::CompressedMatrix 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 v1( 5UL ); + blaze::CompressedVector 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::DynamicVectorv1( 100UL ), v2( 100UL ), v3; + + // ... Initialization of the vectors + + v3 = v1 + v2; // Vectorized addition of two double precision vectors + \endcode + + \code + blaze::DynamicMatrix 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     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 v1( 5UL ), v3; + blaze::CompressedVector v2( 5UL ); + + // ... Initializing the vectors + + v3 = v1 - v2; // Subtraction of a two column vectors of different data type + + + blaze::DynamicMatrix M1( 7UL, 3UL ); + blaze::CompressedMatrix 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 v1( 5UL ); + blaze::CompressedVector 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::DynamicVectorv1( 100UL ), v2( 100UL ), v3; + + // ... Initialization of the vectors + + v3 = v1 - v2; // Vectorized subtraction of two double precision vectors + + + blaze::DynamicMatrix 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     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 v1{ 1, 2, 3 }; + + blaze::DynamicVector v2 = v1 * 1.2; + blaze::CompressedVector v3 = -0.3F * v1; + \endcode + + \code + blaze::StaticMatrix M1{ { 1, 2 }, { 3, 4 }, { 5, 6 } }; + + blaze::DynamicMatrix M2 = M1 * 1.2; + blaze::CompressedMatrix 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 > M1; + blaze::StaticMatrix scalar; + + M1 * scalar; // No scalar multiplication, but matrix/matrix multiplication + + M1.scale( scalar ); // Scalar multiplication + \endcode + +// \n Previous: \ref subtraction     Next: \ref componentwise_multiplication +*/ +//************************************************************************************************* + + +//**Vector/Vector Multiplication******************************************************************* +/*!\page vector_vector_multiplication Vector/Vector Multiplication +// +// \n \section componentwise_multiplication Componentwise Multiplication +//
+// +// 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 v1( 17UL ); + DynamicVector v2( 17UL ); + + StaticVector v3; + DynamicVector v4( 10UL ); + + // ... Initialization of the vectors + + CompressedVector v5( v1 * v2 ); // Componentwise multiplication of a sparse and + // a dense column vector. The result is a sparse + // column vector. + DynamicVector 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 +//
+// +// The multiplication between a row vector and a column vector results in an inner product between +// the two vectors: + + \code + blaze::StaticVector v1{ 2, 5, -1 }; + blaze::DynamicVector 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 v1{ 2, 5, -1 }; + blaze::StaticVector 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 v1{ 2, 5, -1 }; + blaze::StaticVector v2{ -1, 3, -2 }; + + int result = dot( v1, v2 ); // Inner product between two row vectors + \endcode + + \code + blaze::StaticVector v1{ 2, 5, -1 }; + blaze::StaticVector 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 +//
+// +// The multiplication between a column vector and a row vector results in the outer product of +// the two vectors: + + \code + blaze::StaticVector v1{ 2, 5, -1 }; + blaze::DynamicVector v2{ -1, 3, -2 }; + + StaticMatrix M1 = v1 * v2; + \endcode + +// The \c trans() function can be used to transpose a vector as necessary: + + \code + blaze::StaticVector v1{ 2, 5, -1 }; + blaze::StaticVector 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 v1{ 2, 5, -1 }; + blaze::StaticVector v2{ -1, 3, -2 }; + + StaticMatrix M1 = outer( v1, v2 ); // Outer product between two row vectors + \endcode + +// \n \section cross_product Cross Product +//
+// +// 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 v1{ 2, 5, -1 }; + blaze::DynamicVector v2{ -1, 3, -2 }; + + blaze::StaticVector v3( cross( v1, v2 ) ); + blaze::StaticVector 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     Next: \ref vector_vector_division +*/ +//************************************************************************************************* + + +//**Vector/Vector Division************************************************************************* +/*!\page vector_vector_division Vector/Vector Division +// +// \n \section componentwise_division Componentwise Division +//
+// +// 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 v1( 17UL ); + DynamicVector v2( 17UL ); + + StaticVector v3; + DynamicVector v4( 10UL ); + + // ... Initialization of the vectors + + CompressedVector v5( v1 / v2 ); // Componentwise division of a sparse and a + // dense column vector. The result is a sparse + // column vector. + DynamicVector 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     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 M1( 39UL, 12UL ); + StaticVector v1; + + // ... Initialization of the matrix and the vector + + DynamicVector v2 = M1 * v1; // Matrix/column vector multiplication + DynamicVector 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     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 M1( 45UL, 85UL ); + CompressedMatrix M2( 85UL, 37UL ); + + // ... Initialization of the matrices + + DynamicMatrix 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     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 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: +// +//
    +//
  • SIMD data types for fundamental data types +//
      +//
    • \c blaze::SIMDint8: Packed SIMD type for 8-bit signed integral data types
    • +//
    • \c blaze::SIMDuint8: Packed SIMD type for 8-bit unsigned integral data types
    • +//
    • \c blaze::SIMDint16: Packed SIMD type for 16-bit signed integral data types
    • +//
    • \c blaze::SIMDuint16: Packed SIMD type for 16-bit unsigned integral data types
    • +//
    • \c blaze::SIMDint32: Packed SIMD type for 32-bit signed integral data types
    • +//
    • \c blaze::SIMDuint32: Packed SIMD type for 32-bit unsigned integral data types
    • +//
    • \c blaze::SIMDint64: Packed SIMD type for 64-bit signed integral data types
    • +//
    • \c blaze::SIMDuint64: Packed SIMD type for 64-bit unsigned integral data types
    • +//
    • \c blaze::SIMDfloat: Packed SIMD type for single precision floating point data
    • +//
    • \c blaze::SIMDdouble: Packed SIMD type for double precision floating point data
    • +//
    +//
  • +//
  • SIMD data types for complex data types +//
      +//
    • \c blaze::cint8: Packed SIMD type for complex 8-bit signed integral data types
    • +//
    • \c blaze::cuint8: Packed SIMD type for complex 8-bit unsigned integral data types
    • +//
    • \c blaze::cint16: Packed SIMD type for complex 16-bit signed integral data types
    • +//
    • \c blaze::cuint16: Packed SIMD type for complex 16-bit unsigned integral data types
    • +//
    • \c blaze::cint32: Packed SIMD type for complex 32-bit signed integral data types
    • +//
    • \c blaze::cuint32: Packed SIMD type for complex 32-bit unsigned integral data types
    • +//
    • \c blaze::cint64: Packed SIMD type for complex 64-bit signed integral data types
    • +//
    • \c blaze::cuint64: Packed SIMD type for complex 64-bit unsigned integral data types
    • +//
    • \c blaze::cfloat: Packed SIMD type for complex single precision floating point data
    • +//
    • \c blaze::cdouble: Packed SIMD type for complex double precision floating point data
    • +//
    +//
  • +//
+// +// 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::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     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     Next: \ref openmp_parallelization +*/ +//************************************************************************************************* + + +//**OpenMP Parallelization************************************************************************* +/*!\page openmp_parallelization OpenMP Parallelization +// +// \tableofcontents +// +// +// \n \section openmp_setup OpenMP Setup +//
+// +// 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 +//
+// +// 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 +// ./blaze/config/Thresholds.h. +// +// 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 +//
+// +// 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 a( N ), b( N ), c( N ), d( N ); + + // Initialization of the vectors b, c, and d + for( size_t i=0UL; i(); + c[i] = rand(); + d[i] = rand(); + } + + // 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(); + c[i] = rand(); + d[i] = rand(); + } + + // ... + \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 +//
+// +// 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 x, y1, y2; + blaze::DynamicMatrix 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 x, y1, y2; + blaze::DynamicMatrix 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 x, y1, y2; + blaze::DynamicMatrix 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     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 +//
+// +// 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 +//
+// +// 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 ./blaze/config/Thresholds.h. +// +// 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 +//
+// +// 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     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 +//
+// +// 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 +//
+// +// 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 ./blaze/config/Thresholds.h. +// +// 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     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 +//
+// +// The first option is the serialization of a specific operation via the \c serial() function: + + \code + blaze::DynamicMatrix 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 +//
+// +// 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 A; + blaze::DynamicVector 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 +//
+// +// 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 ./blaze/config/SMP.h 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     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     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 d; + blaze::CompressedVector s; + + // ... Resizing and initialization + + // Creating an archive that writes into a the file "vectors.blaze" + blaze::Archive 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 d1; + blaze::DynamicVector d2; + + // Creating an archive that reads from the file "vectors.blaze" + blaze::Archive 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 > > vec; + + // ... Resizing and initialization + + // Creating an archive that writes into a the file "vector.blaze" + blaze::Archive archive( "vector.blaze" ); + + // Serialization of the vector into the archive + archive << vec; + } + + // Deserialization + { + blaze::CompressedVector< blaze::DynamicVector< blaze::complex > > vec; + + // Creating an archive that reads from the file "vector.blaze" + blaze::Archive 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     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 D; + blaze::CompressedMatrix S; + + // ... Resizing and initialization + + // Creating an archive that writes into a the file "matrices.blaze" + blaze::Archive 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 D1; + blaze::DynamicMatrix D2; + + // Creating an archive that reads from the file "matrices.blaze" + blaze::Archive 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 > > mat; + + // ... Resizing and initialization + + // Creating an archive that writes into a the file "matrix.blaze" + blaze::Archive archive( "matrix.blaze" ); + + // Serialization of the matrix into the archive + archive << mat; + } + + // Deserialization + { + blaze::CompressedMatrix< blaze::DynamicMatrix< blaze::complex > > mat; + + // Creating an archive that reads from the file "matrix.blaze" + blaze::Archive 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     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 +//
+// +// \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 dot( const int n, const complex* x, const int incX, + const complex* y, const int incY ); + + complex dot( const int n, const complex* x, const int incX, + const complex* y, const int incY ); + + template< typename VT1, bool TF1, typename VT2, bool TF2 > + ElementType_ dot( const DenseVector& x, const DenseVector& y ); + + } // namespace blaze + \endcode + +// \n \section blas_level_2 BLAS Level 2 +//
+// +// \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 alpha, + const complex* A, int lda, const complex* x, int incX, + complex beta, complex* y, int incY ); + + void gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, int m, int n, complex alpha, + const complex* A, int lda, const complex* x, int incX, + complex beta, complex* y, int incY ); + + template< typename VT1, typename MT1, bool SO, typename VT2, typename ST > + void gemv( DenseVector& y, const DenseMatrix& A, + const DenseVector& x, ST alpha, ST beta ); + + template< typename VT1, typename VT2, typename MT1, bool SO, typename ST > + void gemv( DenseVector& y, const DenseVector& x, + const DenseMatrix& 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* A, int lda, complex* x, int incX ); + + void trmv( CBLAS_ORDER order, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA, CBLAS_DIAG diag, + int n, const complex* A, int lda, complex* x, int incX ); + + template< typename VT, typename MT, bool SO > + void trmv( DenseVector& x, const DenseMatrix& A, CBLAS_UPLO uplo ); + + template< typename VT, typename MT, bool SO > + void trmv( DenseVector& x, const DenseMatrix& A, CBLAS_UPLO uplo ); + + } // namespace blaze + \endcode + +// \n \section blas_level_3 BLAS Level 3 +//
+// +// \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 alpha, const complex* A, int lda, + const complex* B, int ldb, complex beta, float* C, int ldc ); + + void gemm( CBLAS_ORDER order, CBLAS_TRANSPOSE transA, CBLAS_TRANSPOSE transB, + int m, int n, int k, complex alpha, const complex* A, int lda, + const complex* B, int ldb, complex beta, float* C, int ldc ); + + template< typename MT1, bool SO1, typename MT2, bool SO2, typename MT3, bool SO3, typename ST > + void gemm( DenseMatrix& C, const DenseMatrix& A, + const DenseMatrix& 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 alpha, const complex* A, + int lda, complex* 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 alpha, const complex* A, + int lda, complex* B, int ldb ); + + template< typename MT1, bool SO1, typename MT2, bool SO2, typename ST > + void trmm( DenseMatrix& B, const DenseMatrix& 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 alpha, const complex* A, + int lda, complex* 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 alpha, const complex* A, + int lda, complex* B, int ldb ); + + template< typename MT, bool SO, typename VT, bool TF, typename ST > + void trsm( const DenseMatrix& A, DenseVector& b, + CBLAS_SIDE side, CBLAS_UPLO uplo, ST alpha ); + + template< typename MT1, bool SO1, typename MT2, bool SO2, typename ST > + void trsm( const DenseMatrix& A, DenseMatrix& B, + CBLAS_SIDE side, CBLAS_UPLO uplo, ST alpha ); + + } // namespace blaze + \endcode + +// \n Previous: \ref matrix_serialization     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, or \c complex 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 +//
+// +// 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* A, int lda, int* ipiv, int* info ); + + void getrf( int m, int n, complex* A, int lda, int* ipiv, int* info ); + + template< typename MT, bool SO > + void getrf( DenseMatrix& 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* A, int lda, int* ipiv, complex* work, int lwork, int* info ); + + void sytrf( char uplo, int n, complex* A, int lda, int* ipiv, complex* work, int lwork, int* info ); + + template< typename MT, bool SO > + void sytrf( DenseMatrix& 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* A, int lda, int* ipiv, complex* work, int lwork, int* info ); + + void hetrf( char uplo, int n, complex* A, int lda, int* ipiv, complex* work, int lwork, int* info ); + + template< typename MT, bool SO > + void hetrf( DenseMatrix& 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* A, int lda, int* info ); + + void potrf( char uplo, int n, complex* A, int lda, int* info ); + + template< typename MT, bool SO > + void potrf( DenseMatrix& 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* A, int lda, complex* tau, complex* work, int lwork, int* info ); + + void geqrf( int m, int n, complex* A, int lda, complex* tau, complex* work, int lwork, int* info ); + + template< typename MT, bool SO > + void geqrf( DenseMatrix& 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 v(0:i-1) = 0 and +// v(i) = 1. v(i+1:m) is stored on exit in A(i+1:m,i), 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* A, int lda, const complex* tau, complex* work, int lwork, int* info ); + + void ungqr( int m, int n, int k, complex* A, int lda, const complex* tau, complex* work, int lwork, int* info ); + + template< typename MT, bool SO > + void orgqr( DenseMatrix& A, const typename MT::ElementType* tau ); + + template< typename MT, bool SO > + void ungqr( DenseMatrix& 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* A, int lda, const complex* tau, complex* C, int ldc, complex* work, int lwork, int* info ); + + void unmqr( char side, char trans, int m, int n, int k, const complex* A, int lda, const complex* tau, complex* C, int ldc, complex* work, int lwork, int* info ); + + template< typename MT1, bool SO1, typename MT2, bool SO2 > + void ormqr( DenseMatrix& C, const DenseMatrix& A, char side, char trans, const ElementType_* tau ); + + template< typename MT1, bool SO, typename MT2 > + void unmqr( DenseMatrix& C, DenseMatrix& A, char side, char trans, ElementType_* 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* A, int lda, complex* tau, complex* work, int lwork, int* info ); + + void gerqf( int m, int n, complex* A, int lda, complex* tau, complex* work, int lwork, int* info ); + + template< typename MT, bool SO > + void gerqf( DenseMatrix& 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 v(n-k+i+1:n) = 0 and +// v(n-k+i) = 1. v(1:n-k+i-1) is stored on exit in A(m-k+i,1:n-k+i-1), +// 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 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* A, int lda, const complex* tau, complex* work, int lwork, int* info ); + + void ungrq( int m, int n, int k, complex* A, int lda, const complex* tau, complex* work, int lwork, int* info ); + + template< typename MT, bool SO > + void orgrq( DenseMatrix& A, const typename MT::ElementType* tau ); + + template< typename MT, bool SO > + void ungrq( DenseMatrix& 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* A, int lda, const complex* tau, complex* C, int ldc, complex* work, int lwork, int* info ); + + void unmrq( char side, char trans, int m, int n, int k, const complex* A, int lda, const complex* tau, complex* C, int ldc, complex* work, int lwork, int* info ); + + template< typename MT1, bool SO1, typename MT2, bool SO2 > + void ormrq( DenseMatrix& C, const DenseMatrix& A, char side, char trans, const ElementType_* tau ); + + template< typename MT1, bool SO, typename MT2 > + void unmrq( DenseMatrix& C, DenseMatrix& A, char side, char trans, ElementType_* 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* A, int lda, complex* tau, complex* work, int lwork, int* info ); + + void geqlf( int m, int n, complex* A, int lda, complex* tau, complex* work, int lwork, int* info ); + + template< typename MT, bool SO > + void geqlf( DenseMatrix& 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 v(m-k+i+1:m) = 0 and +// v(m-k+i) = 1. v(1:m-k+i-1) is stored on exit in A(1:m-k+i-1,n-k+i), +// 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* A, int lda, const complex* tau, complex* work, int lwork, int* info ); + + void ungql( int m, int n, int k, complex* A, int lda, const complex* tau, complex* work, int lwork, int* info ); + + template< typename MT, bool SO > + void orgql( DenseMatrix& A, const typename MT::ElementType* tau ); + + template< typename MT, bool SO > + void ungql( DenseMatrix& 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* A, int lda, const complex* tau, complex* C, int ldc, complex* work, int lwork, int* info ); + + void unmql( char side, char trans, int m, int n, int k, const complex* A, int lda, const complex* tau, complex* C, int ldc, complex* work, int lwork, int* info ); + + template< typename MT1, bool SO1, typename MT2, bool SO2 > + void ormql( DenseMatrix& C, const DenseMatrix& A, char side, char trans, const ElementType_* tau ); + + template< typename MT1, bool SO, typename MT2 > + void unmql( DenseMatrix& C, DenseMatrix& A, char side, char trans, ElementType_* 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* A, int lda, complex* tau, complex* work, int lwork, int* info ); + + void gelqf( int m, int n, complex* A, int lda, complex* tau, complex* work, int lwork, int* info ); + + template< typename MT, bool SO > + void gelqf( DenseMatrix& 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 v(0:i-1) = 0 and +// v(i) = 1. v(i+1:n) is stored on exit in A(i,i+1:n), 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* A, int lda, const complex* tau, complex* work, int lwork, int* info ); + + void unglq( int m, int n, int k, complex* A, int lda, const complex* tau, complex* work, int lwork, int* info ); + + template< typename MT, bool SO > + void orglq( DenseMatrix& A, const typename MT::ElementType* tau ); + + template< typename MT, bool SO > + void unglq( DenseMatrix& 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* A, int lda, const complex* tau, complex* C, int ldc, complex* work, int lwork, int* info ); + + void unmlq( char side, char trans, int m, int n, int k, const complex* A, int lda, const complex* tau, complex* C, int ldc, complex* work, int lwork, int* info ); + + template< typename MT1, bool SO1, typename MT2, bool SO2 > + void ormlq( DenseMatrix& C, const DenseMatrix& A, char side, char trans, const ElementType_* tau ); + + template< typename MT1, bool SO, typename MT2 > + void unmlq( DenseMatrix& C, DenseMatrix& A, char side, char trans, ElementType_* tau ); + + } // namespace blaze + \endcode + +// \n \section lapack_inversion Matrix Inversion +//
+// +// 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* A, int lda, const int* ipiv, complex* work, int lwork, int* info ); + + void getri( int n, complex* A, int lda, const int* ipiv, complex* work, int lwork, int* info ); + + template< typename MT, bool SO > + void getri( DenseMatrix& 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* A, int lda, const int* ipiv, complex* work, int* info ); + + void sytri( char uplo, int n, complex* A, int lda, const int* ipiv, complex* work, int* info ); + + template< typename MT, bool SO > + void sytri( DenseMatrix& 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* A, int lda, const int* ipiv, complex* work, int* info ); + + void hetri( char uplo, int n, complex* A, int lda, const int* ipiv, complex* work, int* info ); + + template< typename MT, bool SO > + void hetri( DenseMatrix& 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* A, int lda, int* info ); + + void potri( char uplo, int n, complex* A, int lda, int* info ); + + template< typename MT, bool SO > + void potri( DenseMatrix& 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* A, int lda, int* info ); + + void trtri( char uplo, char diag, int n, complex* A, int lda, int* info ); + + template< typename MT, bool SO > + void trtri( DenseMatrix& 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 +//
+// +// 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* A, int lda, const int* ipiv, complex* B, int ldb, int* info ); + + void getrs( char trans, int n, const complex* A, int lda, const int* ipiv, complex* B, int ldb, int* info ); + + template< typename MT, bool SO, typename VT, bool TF > + void getrs( const DenseMatrix& A, DenseVector& b, char trans, const int* ipiv ); + + template< typename MT1, bool SO1, typename MT2, bool SO2 > + void getrs( const DenseMatrix& A, DenseMatrix& 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* A, int lda, const int* ipiv, complex* B, int ldb, int* info ); + + void sytrs( char uplo, int n, int nrhs, const complex* A, int lda, const int* ipiv, complex* B, int ldb, int* info ); + + template< typename MT, bool SO, typename VT, bool TF > + void sytrs( const DenseMatrix& A, DenseVector& b, char uplo, const int* ipiv ); + + template< typename MT1, bool SO1, typename MT2, bool SO2 > + void sytrs( const DenseMatrix& A, DenseMatrix& 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* A, int lda, const int* ipiv, complex* B, int ldb, int* info ); + + void hetrs( char uplo, int n, int nrhs, const complex* A, int lda, const int* ipiv, complex* B, int ldb, int* info ); + + template< typename MT, bool SO, typename VT, bool TF > + void hetrs( const DenseMatrix& A, DenseVector& b, char uplo, const int* ipiv ); + + template< typename MT1, bool SO1, typename MT2, bool SO2 > + void hetrs( const DenseMatrix& A, DenseMatrix& 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* A, int lda, complex* B, int ldb, int* info ); + + void potrs( char uplo, int n, int nrhs, const complex* A, int lda, complex* B, int ldb, int* info ); + + template< typename MT, bool SO, typename VT, bool TF > + void potrs( const DenseMatrix& A, DenseVector& b, char uplo ); + + template< typename MT1, bool SO1, typename MT2, bool SO2 > + void potrs( const DenseMatrix& A, DenseMatrix& 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* A, int lda, complex* B, int ldb, int* info ); + + void trtrs( char uplo, char trans, char diag, int n, int nrhs, const complex* A, int lda, complex* B, int ldb, int* info ); + + template< typename MT, bool SO, typename VT, bool TF > + void trtrs( const DenseMatrix& A, DenseVector& b, char uplo, char trans, char diag ); + + template< typename MT1, bool SO1, typename MT2, bool SO2 > + void trtrs( const DenseMatrix& A, DenseMatrix& 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 +//
+// +// 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* A, int lda, int* ipiv, complex* B, int ldb, int* info ); + + void gesv( int n, int nrhs, complex* A, int lda, int* ipiv, complex* B, int ldb, int* info ); + + template< typename MT, bool SO, typename VT, bool TF > + void gesv( DenseMatrix& A, DenseVector& b, int* ipiv ); + + template< typename MT1, bool SO1, typename MT2, bool SO2 > + void gesv( DenseMatrix& A, DenseMatrix& 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* A, int lda, int* ipiv, complex* B, int ldb, complex* work, int lwork, int* info ); + + void sysv( char uplo, int n, int nrhs, complex* A, int lda, int* ipiv, complex* B, int ldb, complex* work, int lwork, int* info ); + + template< typename MT, bool SO, typename VT, bool TF > + void sysv( DenseMatrix& A, DenseVector& b, char uplo, int* ipiv ); + + template< typename MT1, bool SO1, typename MT2, bool SO2 > + void sysv( DenseMatrix& A, DenseMatrix& 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* A, int lda, int* ipiv, complex* B, int ldb, complex* work, int lwork, int* info ); + + void hesv( char uplo, int n, int nrhs, complex* A, int lda, int* ipiv, complex* B, int ldb, complex* work, int lwork, int* info ); + + template< typename MT, bool SO, typename VT, bool TF > + void hesv( DenseMatrix& A, DenseVector& b, char uplo, int* ipiv ); + + template< typename MT1, bool SO1, typename MT2, bool SO2 > + void hesv( DenseMatrix& A, DenseMatrix& 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* A, int lda, complex* B, int ldb, int* info ); + + void posv( char uplo, int n, int nrhs, complex* A, int lda, complex* B, int ldb, int* info ); + + template< typename MT, bool SO, typename VT, bool TF > + void posv( DenseMatrix& A, DenseVector& b, char uplo ); + + template< typename MT1, bool SO1, typename MT2, bool SO2 > + void posv( DenseMatrix& A, DenseMatrix& 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* A, int lda, complex* x, int incX ); + + void trsv( char uplo, char trans, char diag, int n, const complex* A, int lda, complex* x, int incX ); + + template< typename MT, bool SO, typename VT, bool TF > + void trsv( const DenseMatrix& A, DenseVector& 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     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 ./blaze/config/ 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 +//
+// +// The \b Blaze default is that all vectors are created as column vectors (if not specified +// explicitly): + + \code + blaze::StaticVector x; // Creates a 3-dimensional static column vector + \endcode + +// The header file ./blaze/config/TransposeFlag.h 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 +//
+// +// Matrices are by default created as row-major matrices: + + \code + blaze::StaticMatrix A; // Creates a 3x3 row-major matrix + \endcode + +// The header file ./blaze/config/StorageOrder.h 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 +//
+// +// 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 ./blaze/config/BLAS.h 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 +//
+// +// 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 +// ./blaze/config/CacheSize.h configuration file: + + \code + constexpr size_t cacheSize = 3145728UL; + \endcode + +// \n \section vectorization Vectorization +//
+// +// 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 +// ./blaze/config/Vectorization.h: + + \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 +//
+// +// \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 +// ./blaze/config/Thresholds.h. +// +// +// \n \section padding Padding +//
+// +// 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 ./blaze/config/Optimizations.h 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) +//
+// +// 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 ./blaze/config/Optimizations.h 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     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 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 { + typedef custom::double_t Type; + }; + + template<> + struct SubTrait { + typedef custom::double_t Type; + }; + + template<> + struct MultTrait { + typedef custom::double_t Type; + }; + + template<> + struct DivTrait { + 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     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 +//
+// +// 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 +//
+// +// 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 + \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 +//
+// +// 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 + \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 +//
+// +// 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     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 d1, d2, d3; + blaze::CompressedVector 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 A, B; + blaze::DynamicVector 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 d1, d2, d3; + blaze::CompressedVector 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 A, B, C; + blaze::DynamicVector 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 d1, d2, d3; + blaze::CompressedVector s1; + + // ... Resizing and initialization + + d3 = d1 + eval( s1 + d2 ); + \endcode + + \code + blaze::DynamicMatrix A, B; + blaze::DynamicVector 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 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 ) 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 +//************************************************************************************************* 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: float, double, long double +*/ +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 A; + + // No explicit specification of the storage order => use of the defaultStorageOrder + StaticMatrix 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 a; + + // No explicit specification of the transpose flag => use of the defaultTransposeFlag + StaticVector 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 +#include + + +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::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& NegativeAccuracy::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::PositiveType NegativeAccuracy::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::operator const T() const +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return -Limits::accuracy(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Accuracy operators */ +//@{ +template< typename A, typename T > +inline bool operator==( const NegativeAccuracy& lhs, const T& rhs ); + +template< typename A, typename T > +inline bool operator==( const T& lhs, const NegativeAccuracy& rhs ); + +template< typename A, typename T > +inline bool operator!=( const NegativeAccuracy& lhs, const T& rhs ); + +template< typename A, typename T > +inline bool operator!=( const T& lhs, const NegativeAccuracy& rhs ); + +template< typename A, typename T > +inline bool operator<( const NegativeAccuracy& lhs, const T& rhs ); + +template< typename A, typename T > +inline bool operator<( const T& lhs, const NegativeAccuracy& rhs ); + +template< typename A, typename T > +inline bool operator>( const NegativeAccuracy& lhs, const T& rhs ); + +template< typename A, typename T > +inline bool operator>( const T& lhs, const NegativeAccuracy& 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& /*lhs*/, const T& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return -Limits::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& /*rhs*/ ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return lhs == -Limits::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& /*lhs*/, const T& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return -Limits::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& /*rhs*/ ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return lhs != -Limits::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& /*lhs*/, const T& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return -Limits::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& /*rhs*/ ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return lhs < -Limits::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& /*lhs*/, const T& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return -Limits::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& /*rhs*/ ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return lhs > -Limits::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& /*lhs*/, const T& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return -Limits::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& /*rhs*/ ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return lhs <= -Limits::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& /*lhs*/, const T& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return -Limits::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& /*rhs*/ ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return lhs >= -Limits::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 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::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::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::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::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::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::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::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::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::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::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::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::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::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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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_; + + 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 VectorType; + + VectorType v( 100UL ); + Subvector sv = subvector( 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 VectorType; + + VectorType v( 100UL ); + Subvector sv = subvector( 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 +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( Column& column ) const; + + template< typename Arg > + inline void randomize( Column& 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 >::randomize( Column& column ) const +{ + using blaze::randomize; + + for( size_t i=0UL; i // Symmetry flag +template< typename Arg > // Min/max argument type +inline void Rand< Column >::randomize( Column& column, + const Arg& min, const Arg& max ) const +{ + using blaze::randomize; + + for( size_t i=0UL; i // Symmetry flag +class Rand< Column > +{ + public: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( Column& column ) const; + inline void randomize( Column& column, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( Column& column, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( Column& 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 >::randomize( Column& column ) const +{ + typedef ElementType_< Column > ElementType; + + const size_t size( column.size() ); + + if( size == 0UL ) return; + + const size_t nonzeros( rand( 1UL, std::ceil( 0.5*size ) ) ); + + column.reset(); + column.reserve( nonzeros ); + + while( column.nonZeros() < nonzeros ) { + column[ rand( 0UL, size-1UL ) ] = rand(); + } +} +/*! \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 >::randomize( Column& column, size_t nonzeros ) const +{ + typedef ElementType_< Column > 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( 0UL, size-1UL ) ] = rand(); + } +} +/*! \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 >::randomize( Column& column, + const Arg& min, const Arg& max ) const +{ + typedef ElementType_< Column > ElementType; + + const size_t size( column.size() ); + + if( size == 0UL ) return; + + const size_t nonzeros( rand( 1UL, std::ceil( 0.5*size ) ) ); + + column.reset(); + column.reserve( nonzeros ); + + while( column.nonZeros() < nonzeros ) { + column[ rand( 0UL, size-1UL ) ] = rand( 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 >::randomize( Column& column, size_t nonzeros, + const Arg& min, const Arg& max ) const +{ + typedef ElementType_< Column > 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( 0UL, size-1UL ) ] = rand( 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const CompressedMatrix generate( size_t m, size_t n ) const; + inline const CompressedMatrix generate( size_t m, size_t n, size_t nonzeros ) const; + + template< typename Arg > + inline const CompressedMatrix generate( size_t m, size_t n, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const CompressedMatrix 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& matrix ) const; + inline void randomize( CompressedMatrix& matrix, size_t nonzeros ) const; + inline void randomize( CompressedMatrix& matrix, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( CompressedMatrix& matrix, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( CompressedMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + template< typename Arg > + inline void randomize( CompressedMatrix& 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 + Rand< CompressedMatrix >::generate( size_t m, size_t n ) const +{ + CompressedMatrix 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 + Rand< CompressedMatrix >::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 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 + Rand< CompressedMatrix >::generate( size_t m, size_t n, const Arg& min, const Arg& max ) const +{ + CompressedMatrix 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 + Rand< CompressedMatrix >::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 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 >::randomize( CompressedMatrix& 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( 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 >::randomize( CompressedMatrix& 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 dist( m ); + + for( size_t nz=0UL; nz( 0UL, m-1UL ); + if( dist[index] == n ) continue; + ++dist[index]; + ++nz; + } + + for( size_t i=0UL; i() ); + } + 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 >::randomize( CompressedMatrix& 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 dist( n ); + + for( size_t nz=0UL; nz( 0UL, n-1UL ); + if( dist[index] == m ) continue; + ++dist[index]; + ++nz; + } + + for( size_t j=0UL; j() ); + } + 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 >::randomize( CompressedMatrix& 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( 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 >::randomize( CompressedMatrix& 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 dist( m ); + + for( size_t nz=0UL; nz( 0UL, m-1UL ); + if( dist[index] == n ) continue; + ++dist[index]; + ++nz; + } + + for( size_t i=0UL; i( 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 >::randomize( CompressedMatrix& 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 dist( n ); + + for( size_t nz=0UL; nz( 0UL, n-1UL ); + if( dist[index] == m ) continue; + ++dist[index]; + ++nz; + } + + for( size_t j=0UL; j( 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 +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const CompressedVector generate( size_t size ) const; + inline const CompressedVector generate( size_t size, size_t nonzeros ) const; + + template< typename Arg > + inline const CompressedVector generate( size_t size, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const CompressedVector generate( size_t size, size_t nonzeros, const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( CompressedVector& vector ) const; + inline void randomize( CompressedVector& vector, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( CompressedVector& vector, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( CompressedVector& 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 + Rand< CompressedVector >::generate( size_t size ) const +{ + CompressedVector 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 + Rand< CompressedVector >::generate( size_t size, size_t nonzeros ) const +{ + if( nonzeros > size ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + CompressedVector 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 + Rand< CompressedVector >::generate( size_t size, const Arg& min, const Arg& max ) const +{ + CompressedVector 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 + Rand< CompressedVector >::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 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 >::randomize( CompressedVector& vector ) const +{ + const size_t size( vector.size() ); + + if( size == 0UL ) return; + + const size_t nonzeros( rand( 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 >::randomize( CompressedVector& 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() ); + } +} +/*! \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 >::randomize( CompressedVector& vector, + const Arg& min, const Arg& max ) const +{ + const size_t size( vector.size() ); + + if( size == 0UL ) return; + + const size_t nonzeros( rand( 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 >::randomize( CompressedVector& 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( 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 +#include + + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( CustomMatrix& matrix ) const; + + template< typename Arg > + inline void randomize( CustomMatrix& 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 >::randomize( CustomMatrix& matrix ) const +{ + using blaze::randomize; + + const size_t m( matrix.rows() ); + const size_t n( matrix.columns() ); + + for( size_t i=0UL; i // Storage order +template< typename Arg > // Min/max argument type +inline void Rand< CustomMatrix >::randomize( CustomMatrix& 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 // Storage order +void makeSymmetric( CustomMatrix& 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 // Min/max argument type +void makeSymmetric( CustomMatrix& 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 // Storage order +void makeHermitian( CustomMatrix& matrix ) +{ + using blaze::randomize; + + BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type ); + + typedef UnderlyingBuiltin_ 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(); + } + + 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& matrix, const Arg& min, const Arg& max ) +{ + using blaze::randomize; + + BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type ); + + typedef UnderlyingBuiltin_ 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( 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& 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 +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( CustomVector& vector ) const; + + template< typename Arg > + inline void randomize( CustomVector& 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 >::randomize( CustomVector& vector ) const +{ + using blaze::randomize; + + const size_t size( vector.size() ); + for( size_t i=0UL; i // Transpose flag +template< typename Arg > // Min/max argument type +inline void Rand< CustomVector >::randomize( CustomVector& vector, + const Arg& min, const Arg& max ) const +{ + using blaze::randomize; + + const size_t size( vector.size() ); + for( size_t i=0UL; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const DiagonalMatrix generate() const; + inline const DiagonalMatrix generate( size_t n ) const; + inline const DiagonalMatrix generate( size_t n, size_t nonzeros ) const; + + template< typename Arg > + inline const DiagonalMatrix generate( const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const DiagonalMatrix generate( size_t n, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const DiagonalMatrix generate( size_t n, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( DiagonalMatrix& matrix ) const; + inline void randomize( DiagonalMatrix& matrix, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( DiagonalMatrix& matrix, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( DiagonalMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + private: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( DiagonalMatrix& matrix, TrueType ) const; + inline void randomize( DiagonalMatrix& matrix, FalseType ) const; + + template< typename Arg > + inline void randomize( DiagonalMatrix& matrix, const Arg& min, const Arg& max, TrueType ) const; + + template< typename Arg > + inline void randomize( DiagonalMatrix& 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 Rand< DiagonalMatrix >::generate() const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + DiagonalMatrix 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 + Rand< DiagonalMatrix >::generate( size_t n ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + DiagonalMatrix 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 + Rand< DiagonalMatrix >::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 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 + Rand< DiagonalMatrix >::generate( const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + DiagonalMatrix 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 + Rand< DiagonalMatrix >::generate( size_t n, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + DiagonalMatrix 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 + Rand< DiagonalMatrix >::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::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + DiagonalMatrix 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 >::randomize( DiagonalMatrix& matrix ) const +{ + randomize( matrix, typename IsDenseMatrix::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 >::randomize( DiagonalMatrix& matrix, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i(); + } +} +/*! \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 >::randomize( DiagonalMatrix& 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( 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 >::randomize( DiagonalMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ 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() ); + } + + for( ; i // Numeric flag +template< typename Arg > // Min/max argument type +inline void Rand< DiagonalMatrix >::randomize( DiagonalMatrix& matrix, + const Arg& min, const Arg& max ) const +{ + randomize( matrix, min, max, typename IsDenseMatrix::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 >::randomize( DiagonalMatrix& matrix, + const Arg& min, const Arg& max, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i( 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 >::randomize( DiagonalMatrix& 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( 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 >::randomize( DiagonalMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ 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( min, max ) ); + } + + for( ; i // Density flag +void makeSymmetric( DiagonalMatrix& matrix ) +{ + const size_t n( matrix.rows() ); + + reset( matrix ); + + for( size_t i=0UL; i >(); + } + + 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& matrix, const Arg& min, const Arg& max ) +{ + typedef ElementType_ Type; + + const size_t n( matrix.rows() ); + + reset( matrix ); + + for( size_t i=0UL; i( 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& matrix ) +{ + typedef UnderlyingBuiltin_< ElementType_ > Type; + + const size_t n( matrix.rows() ); + + reset( matrix ); + + for( size_t i=0UL; i(); + } + + 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& matrix, const Arg& min, const Arg& max ) +{ + typedef UnderlyingBuiltin_< ElementType_ > Type; + + const size_t n( matrix.rows() ); + + reset( matrix ); + + for( size_t i=0UL; i( 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const DynamicMatrix generate( size_t m, size_t n ) const; + + template< typename Arg > + inline const DynamicMatrix generate( size_t m, size_t n, const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( DynamicMatrix& matrix ) const; + + template< typename Arg > + inline void randomize( DynamicMatrix& 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 + Rand< DynamicMatrix >::generate( size_t m, size_t n ) const +{ + DynamicMatrix 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 + Rand< DynamicMatrix >::generate( size_t m, size_t n, const Arg& min, const Arg& max ) const +{ + DynamicMatrix 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 >::randomize( DynamicMatrix& matrix ) const +{ + using blaze::randomize; + + const size_t m( matrix.rows() ); + const size_t n( matrix.columns() ); + + for( size_t i=0UL; i // Storage order +template< typename Arg > // Min/max argument type +inline void Rand< DynamicMatrix >::randomize( DynamicMatrix& 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 // Storage order +void makeSymmetric( DynamicMatrix& 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 // Min/max argument type +void makeSymmetric( DynamicMatrix& 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 // Storage order +void makeHermitian( DynamicMatrix& matrix ) +{ + using blaze::randomize; + + BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type ); + + typedef UnderlyingBuiltin_ 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(); + } + + 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& matrix, const Arg& min, const Arg& max ) +{ + using blaze::randomize; + + BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type ); + + typedef UnderlyingBuiltin_ 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( 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& 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 +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const DynamicVector generate( size_t n ) const; + + template< typename Arg > + inline const DynamicVector generate( size_t n, const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( DynamicVector& vector ) const; + + template< typename Arg > + inline void randomize( DynamicVector& 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 Rand< DynamicVector >::generate( size_t n ) const +{ + DynamicVector 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 + Rand< DynamicVector >::generate( size_t n, const Arg& min, const Arg& max ) const +{ + DynamicVector 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 >::randomize( DynamicVector& vector ) const +{ + using blaze::randomize; + + const size_t size( vector.size() ); + for( size_t i=0UL; i // Transpose flag +template< typename Arg > // Min/max argument type +inline void Rand< DynamicVector >::randomize( DynamicVector& vector, + const Arg& min, const Arg& max ) const +{ + using blaze::randomize; + + const size_t size( vector.size() ); + for( size_t i=0UL; i +#include + + +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::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& NegativeEpsilon::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::PositiveType NegativeEpsilon::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::operator const T() const +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return -Limits::epsilon(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name NegativeEpsilon operators */ +//@{ +template< typename E, typename T > +inline bool operator==( const NegativeEpsilon& lhs, const T& rhs ); + +template< typename E, typename T > +inline bool operator==( const T& lhs, const NegativeEpsilon& rhs ); + +template< typename E, typename T > +inline bool operator!=( const NegativeEpsilon& lhs, const T& rhs ); + +template< typename E, typename T > +inline bool operator!=( const T& lhs, const NegativeEpsilon& rhs ); + +template< typename E, typename T > +inline bool operator<( const NegativeEpsilon& lhs, const T& rhs ); + +template< typename E, typename T > +inline bool operator<( const T& lhs, const NegativeEpsilon& rhs ); + +template< typename E, typename T > +inline bool operator>( const NegativeEpsilon& lhs, const T& rhs ); + +template< typename E, typename T > +inline bool operator>( const T& lhs, const NegativeEpsilon& 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& /*lhs*/, const T& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return -Limits::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& /*rhs*/ ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return lhs == -Limits::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& /*lhs*/, const T& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return -Limits::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& /*rhs*/ ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return lhs != -Limits::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& /*lhs*/, const T& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return -Limits::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& /*rhs*/ ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return lhs < -Limits::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& /*lhs*/, const T& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return -Limits::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& /*rhs*/ ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return lhs > -Limits::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& /*lhs*/, const T& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return -Limits::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& /*rhs*/ ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return lhs <= -Limits::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& /*lhs*/, const T& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return -Limits::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& /*rhs*/ ) +{ + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( T ); + return lhs >= -Limits::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 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::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::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::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::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::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::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::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::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::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::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::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::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::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 + + + + +//================================================================================================= +// +// 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 + \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 + \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 +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ + min( const T1& a, const T2& b ) noexcept( All::value ); + +template< typename T1, typename T2, typename... Ts > +BLAZE_ALWAYS_INLINE constexpr CommonType_ + min( const T1& a, const T2& b, const Ts&... args ) noexcept( All::value ); + +template< typename T1, typename T2 > +BLAZE_ALWAYS_INLINE constexpr CommonType_ + max( const T1& a, const T2& b ) noexcept( All::value ); + +template< typename T1, typename T2, typename... Ts > +BLAZE_ALWAYS_INLINE constexpr CommonType_ + max( const T1& a, const T2& b, const Ts&... args ) noexcept( All::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_ >::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::value || IsFloatingPoint::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_ + min( const T1& a, const T2& b ) noexcept( All::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_ + min( const T1& a, const T2& b, const Ts&... args ) noexcept( All::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_ + max( const T1& a, const T2& b ) noexcept( All::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_ + max( const T1& a, const T2& b, const Ts&... args ) noexcept( All::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::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_ >::value ) +{ + return lessThan_backend< CommonType_ >( 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const HermitianMatrix generate() const; + inline const HermitianMatrix generate( size_t n ) const; + inline const HermitianMatrix generate( size_t n, size_t nonzeros ) const; + + template< typename Arg > + inline const HermitianMatrix generate( const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const HermitianMatrix generate( size_t n, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const HermitianMatrix generate( size_t n, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( HermitianMatrix& matrix ) const; + inline void randomize( HermitianMatrix& matrix, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( HermitianMatrix& matrix, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( HermitianMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + private: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( HermitianMatrix& matrix, TrueType ) const; + inline void randomize( HermitianMatrix& matrix, FalseType ) const; + + template< typename Arg > + inline void randomize( HermitianMatrix& matrix, const Arg& min, const Arg& max, TrueType ) const; + + template< typename Arg > + inline void randomize( HermitianMatrix& 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 Rand< HermitianMatrix >::generate() const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + HermitianMatrix 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 + Rand< HermitianMatrix >::generate( size_t n ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + HermitianMatrix 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 + Rand< HermitianMatrix >::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 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 + Rand< HermitianMatrix >::generate( const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + HermitianMatrix 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 + Rand< HermitianMatrix >::generate( size_t n, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + HermitianMatrix 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 + Rand< HermitianMatrix >::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 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 >::randomize( HermitianMatrix& matrix ) const +{ + randomize( matrix, typename IsDenseMatrix::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 >::randomize( HermitianMatrix& matrix, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + typedef UnderlyingBuiltin_ BT; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i(); + } + matrix(i,i) = rand(); + } +} +/*! \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 >::randomize( HermitianMatrix& 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( 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 >::randomize( HermitianMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + typedef UnderlyingBuiltin_ 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( 0UL, n-1UL ) ); + const size_t column( rand( 0UL, n-1UL ) ); + + if( row == column ) + matrix(row,column) = rand(); + else + matrix(row,column) = rand(); + } +} +/*! \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 >::randomize( HermitianMatrix& matrix, + const Arg& min, const Arg& max ) const +{ + randomize( matrix, min, max, typename IsDenseMatrix::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 >::randomize( HermitianMatrix& matrix, + const Arg& min, const Arg& max, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + typedef UnderlyingBuiltin_ BT; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i( min, max ); + } + matrix(i,i) = rand( 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 >::randomize( HermitianMatrix& 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( 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 >::randomize( HermitianMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + typedef UnderlyingBuiltin_ 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( 0UL, n-1UL ) ); + const size_t column( rand( 0UL, n-1UL ) ); + + if( row == column ) + matrix(row,column) = rand( real( min ), real( max ) ); + else + matrix(row,column) = rand( 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& matrix ) +{ + typedef UnderlyingBuiltin_< ElementType_ > BT; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i(); + } + } + + 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& matrix, const Arg& min, const Arg& max ) +{ + typedef UnderlyingBuiltin_< ElementType_ > BT; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i( 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& 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& 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& matrix ) +{ + using blaze::randomize; + + typedef UnderlyingBuiltin_< ElementType_ > BT; + + const size_t n( matrix.rows() ); + + randomize( matrix ); + matrix *= matrix; + + for( size_t i=0UL; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const HybridMatrix generate( size_t m, size_t n ) const; + + template< typename Arg > + inline const HybridMatrix generate( size_t m, size_t n, const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( HybridMatrix& matrix ) const; + + template< typename Arg > + inline void randomize( HybridMatrix& 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 + Rand< HybridMatrix >::generate( size_t m, size_t n ) const +{ + HybridMatrix 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 + Rand< HybridMatrix >::generate( size_t m, size_t n, const Arg& min, const Arg& max ) const +{ + HybridMatrix 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 >::randomize( HybridMatrix& matrix ) const +{ + using blaze::randomize; + + const size_t m( matrix.rows() ); + const size_t n( matrix.columns() ); + + for( size_t i=0UL; i // Storage order +template< typename Arg > // Min/max argument type +inline void Rand< HybridMatrix >::randomize( HybridMatrix& 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 // Storage order +void makeSymmetric( HybridMatrix& 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 // Min/max argument type +void makeSymmetric( HybridMatrix& 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 // Storage order +void makeHermitian( HybridMatrix& matrix ) +{ + using blaze::randomize; + + BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type ); + + typedef UnderlyingBuiltin_ 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(); + } + + 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& matrix, const Arg& min, const Arg& max ) +{ + using blaze::randomize; + + BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type ); + + typedef UnderlyingBuiltin_ 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( 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& 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 +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const HybridVector generate( size_t n ) const; + + template< typename Arg > + inline const HybridVector generate( size_t n, const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( HybridVector& vector ) const; + + template< typename Arg > + inline void randomize( HybridVector& 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 Rand< HybridVector >::generate( size_t n ) const +{ + HybridVector 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 + Rand< HybridVector >::generate( size_t n, const Arg& min, const Arg& max ) const +{ + HybridVector 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 >::randomize( HybridVector& vector ) const +{ + using blaze::randomize; + + for( size_t i=0UL; i // Transpose flag +template< typename Arg > // Min/max argument type +inline void Rand< HybridVector >::randomize( HybridVector& vector, + const Arg& min, const Arg& max ) const +{ + using blaze::randomize; + + for( size_t i=0UL; i +#include +#include +#include + + +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: +// +//
    +//
  • integers
  • +//
      +//
    • signed char, char, wchar_t
    • +//
    • short
    • +//
    • int
    • +//
    • long
    • +//
    • ptrdiff_t (for certain 64-bit compilers)
    • +//
    +//
  • floating points
  • +//
      +//
    • float
    • +//
    • double
    • +//
    • long double
    • +//
    +//
+// +// \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::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::operator signed char() const +{ + return Limits::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::operator char() const +{ + return Limits::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::operator wchar_t() const +{ + return Limits::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::operator short() const +{ + return Limits::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::operator int() const +{ + return Limits::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::operator long() const +{ + return Limits::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::operator ptrdiff_t() const +{ + return Limits::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::operator float() const +{ + return Limits::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::operator double() const +{ + return Limits::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::operator long double() const +{ + return Limits::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::equal( const T& rhs ) const +{ + BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE( T ); + return Limits::ninf() == rhs; +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name NegativeInfinity operators */ +//@{ +template< typename I1, typename I2 > +inline bool operator==( const NegativeInfinity& lhs, const NegativeInfinity& rhs ); + +template< typename I, typename T > +inline bool operator==( const NegativeInfinity& lhs, const T& rhs ); + +template< typename I, typename T > +inline bool operator==( const T& lhs, const NegativeInfinity& rhs ); + +template< typename I1, typename I2 > +inline bool operator!=( const NegativeInfinity& lhs, const NegativeInfinity& rhs ); + +template< typename I, typename T > +inline bool operator!=( const NegativeInfinity& lhs, const T& rhs ); + +template< typename I, typename T > +inline bool operator!=( const T& lhs, const NegativeInfinity& 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& lhs, const NegativeInfinity& 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& 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& 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& lhs, const NegativeInfinity& 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& 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& 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: +// +//
    +//
  • integers
  • +//
      +//
    • unsigned char, signed char, char, wchar_t
    • +//
    • unsigned short, short
    • +//
    • unsigned int, int
    • +//
    • unsigned long, long
    • +//
    +//
  • floating points
  • +//
      +//
    • float
    • +//
    • double
    • +//
    • long double
    • +//
    +//
+// +// 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 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::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::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::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::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::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::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::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::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::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::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::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::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::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::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::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::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& rhs ); + +template< typename I > +inline bool operator==( const NegativeInfinity& 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& rhs ); + +template< typename I > +inline bool operator!=( const NegativeInfinity& 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& 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& 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& 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& 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 +#include + + +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 > 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const LowerMatrix generate() const; + inline const LowerMatrix generate( size_t n ) const; + inline const LowerMatrix generate( size_t n, size_t nonzeros ) const; + + template< typename Arg > + inline const LowerMatrix generate( const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const LowerMatrix generate( size_t n, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const LowerMatrix generate( size_t n, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( LowerMatrix& matrix ) const; + inline void randomize( LowerMatrix& matrix, size_t nonzeros ) const; + inline void randomize( LowerMatrix& matrix, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( LowerMatrix& matrix, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( LowerMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( LowerMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + private: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( LowerMatrix& matrix, TrueType ) const; + inline void randomize( LowerMatrix& matrix, FalseType ) const; + + template< typename Arg > + inline void randomize( LowerMatrix& matrix, const Arg& min, const Arg& max, TrueType ) const; + + template< typename Arg > + inline void randomize( LowerMatrix& 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 Rand< LowerMatrix >::generate() const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + LowerMatrix 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 + Rand< LowerMatrix >::generate( size_t n ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + LowerMatrix 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 + Rand< LowerMatrix >::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::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + LowerMatrix 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 + Rand< LowerMatrix >::generate( const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + LowerMatrix 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 + Rand< LowerMatrix >::generate( size_t n, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + LowerMatrix 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 + Rand< LowerMatrix >::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::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + LowerMatrix 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 >::randomize( LowerMatrix& matrix ) const +{ + randomize( matrix, typename IsDenseMatrix::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 >::randomize( LowerMatrix& matrix, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i(); + } + } +} +/*! \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 >::randomize( LowerMatrix& 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( 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 >::randomize( LowerMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > LowerMatrix::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + if( n == 0UL ) return; + + matrix.reset(); + matrix.reserve( nonzeros ); + + std::vector dist( n ); + + for( size_t nz=0UL; nz( 0UL, n-1UL ); + if( dist[index] == index+1UL ) continue; + ++dist[index]; + ++nz; + } + + for( size_t i=0UL; i() ); + } + 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 >::randomize( LowerMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > LowerMatrix::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + if( n == 0UL ) return; + + matrix.reset(); + matrix.reserve( nonzeros ); + + std::vector dist( n ); + + for( size_t nz=0UL; nz( 0UL, n-1UL ); + if( dist[index] == n - index ) continue; + ++dist[index]; + ++nz; + } + + for( size_t j=0UL; j() ); + } + 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 >::randomize( LowerMatrix& matrix, + const Arg& min, const Arg& max ) const +{ + randomize( matrix, min, max, typename IsDenseMatrix::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 >::randomize( LowerMatrix& matrix, + const Arg& min, const Arg& max, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i( 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 >::randomize( LowerMatrix& 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( 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 >::randomize( LowerMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > LowerMatrix::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + if( n == 0UL ) return; + + matrix.reset(); + matrix.reserve( nonzeros ); + + std::vector dist( n ); + + for( size_t nz=0UL; nz( 0UL, n-1UL ); + if( dist[index] == index+1UL ) continue; + ++dist[index]; + ++nz; + } + + for( size_t i=0UL; i( 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 >::randomize( LowerMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > LowerMatrix::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + if( n == 0UL ) return; + + matrix.reset(); + matrix.reserve( nonzeros ); + + std::vector dist( n ); + + for( size_t nz=0UL; nz( 0UL, n-1UL ); + if( dist[index] == n - index ) continue; + ++dist[index]; + ++nz; + } + + for( size_t j=0UL; j( 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& matrix ) +{ + const size_t n( matrix.rows() ); + + reset( matrix ); + + for( size_t i=0UL; i >(); + } + + 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& matrix, const Arg& min, const Arg& max ) +{ + typedef ElementType_ Type; + + const size_t n( matrix.rows() ); + + reset( matrix ); + + for( size_t i=0UL; i( 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& matrix ) +{ + typedef UnderlyingBuiltin_< ElementType_ > Type; + + const size_t n( matrix.rows() ); + + reset( matrix ); + + for( size_t i=0UL; i(); + } + + 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& matrix, const Arg& min, const Arg& max ) +{ + typedef UnderlyingBuiltin_< ElementType_ > Type; + + const size_t n( matrix.rows() ); + + reset( matrix ); + + for( size_t i=0UL; i( 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& 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 +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Matrix operators */ +//@{ +template< typename MT, bool SO > +inline std::ostream& operator<<( std::ostream& os, const Matrix& 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& m ) +{ + CompositeType_ tmp( ~m ); + + for( size_t i=0UL; i vec( 7UL ); + CustomVector 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 vec( 16UL ); + CustomVector 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 +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( Row& row ) const; + + template< typename Arg > + inline void randomize( Row& 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 >::randomize( Row& row ) const +{ + using blaze::randomize; + + for( size_t i=0UL; i // Symmetry flag +template< typename Arg > // Min/max argument type +inline void Rand< Row >::randomize( Row& row, + const Arg& min, const Arg& max ) const +{ + using blaze::randomize; + + for( size_t i=0UL; i // Symmetry flag +class Rand< Row > +{ + public: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( Row& row ) const; + inline void randomize( Row& row, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( Row& row, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( Row& 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 >::randomize( Row& row ) const +{ + typedef ElementType_< Row > ElementType; + + const size_t size( row.size() ); + + if( size == 0UL ) return; + + const size_t nonzeros( rand( 1UL, std::ceil( 0.5*size ) ) ); + + row.reset(); + row.reserve( nonzeros ); + + while( row.nonZeros() < nonzeros ) { + row[ rand( 0UL, size-1UL ) ] = rand(); + } +} +/*! \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 >::randomize( Row& row, size_t nonzeros ) const +{ + typedef ElementType_< Row > 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( 0UL, size-1UL ) ] = rand(); + } +} +/*! \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 >::randomize( Row& row, + const Arg& min, const Arg& max ) const +{ + typedef ElementType_< Row > ElementType; + + const size_t size( row.size() ); + + if( size == 0UL ) return; + + const size_t nonzeros( rand( 1UL, std::ceil( 0.5*size ) ) ); + + row.reset(); + row.reserve( nonzeros ); + + while( row.nonZeros() < nonzeros ) { + row[ rand( 0UL, size-1UL ) ] = rand( 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 >::randomize( Row& row, size_t nonzeros, + const Arg& min, const Arg& max ) const +{ + typedef ElementType_< Row > 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( 0UL, size-1UL ) ] = rand( 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 +#include +#include +#include + +#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 +#include +#include +#include +#include +#include + +#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 +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const StaticMatrix generate() const; + + template< typename Arg > + inline const StaticMatrix generate( const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( StaticMatrix& matrix ) const; + + template< typename Arg > + inline void randomize( StaticMatrix& 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 Rand< StaticMatrix >::generate() const +{ + StaticMatrix 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 + Rand< StaticMatrix >::generate( const Arg& min, const Arg& max ) const +{ + StaticMatrix 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 >::randomize( StaticMatrix& matrix ) const +{ + using blaze::randomize; + + for( size_t i=0UL; i // Storage order +template< typename Arg > // Min/max argument type +inline void Rand< StaticMatrix >::randomize( StaticMatrix& matrix, + const Arg& min, const Arg& max ) const +{ + using blaze::randomize; + + for( size_t i=0UL; i // Storage order +void makeSymmetric( StaticMatrix& matrix ) +{ + using blaze::randomize; + + BLAZE_STATIC_ASSERT( M == N ); + + for( size_t i=0UL; i // Min/max argument type +void makeSymmetric( StaticMatrix& matrix, const Arg& min, const Arg& max ) +{ + using blaze::randomize; + + BLAZE_STATIC_ASSERT( M == N ); + + for( size_t i=0UL; i // Storage order +void makeHermitian( StaticMatrix& matrix ) +{ + using blaze::randomize; + + BLAZE_STATIC_ASSERT( M == N ); + BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type ); + + typedef UnderlyingBuiltin_ BT; + + for( size_t i=0UL; i(); + } + + 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& matrix, const Arg& min, const Arg& max ) +{ + using blaze::randomize; + + BLAZE_STATIC_ASSERT( M == N ); + BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( Type ); + + typedef UnderlyingBuiltin_ BT; + + for( size_t i=0UL; i( 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& 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 +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const StaticVector generate() const; + + template< typename Arg > + inline const StaticVector generate( const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( StaticVector& vector ) const; + + template< typename Arg > + inline void randomize( StaticVector& 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 Rand< StaticVector >::generate() const +{ + StaticVector 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 + Rand< StaticVector >::generate( const Arg& min, const Arg& max ) const +{ + StaticVector 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 >::randomize( StaticVector& vector ) const +{ + using blaze::randomize; + + for( size_t i=0UL; i // Transpose flag +template< typename Arg > // Min/max argument type +inline void Rand< StaticVector >::randomize( StaticVector& vector, + const Arg& min, const Arg& max ) const +{ + using blaze::randomize; + + for( size_t i=0UL; i 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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const StrictlyLowerMatrix generate() const; + inline const StrictlyLowerMatrix generate( size_t n ) const; + inline const StrictlyLowerMatrix generate( size_t n, size_t nonzeros ) const; + + template< typename Arg > + inline const StrictlyLowerMatrix generate( const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const StrictlyLowerMatrix generate( size_t n, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const StrictlyLowerMatrix generate( size_t n, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( StrictlyLowerMatrix& matrix ) const; + inline void randomize( StrictlyLowerMatrix& matrix, size_t nonzeros ) const; + inline void randomize( StrictlyLowerMatrix& matrix, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( StrictlyLowerMatrix& matrix, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( StrictlyLowerMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( StrictlyLowerMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + private: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( StrictlyLowerMatrix& matrix, TrueType ) const; + inline void randomize( StrictlyLowerMatrix& matrix, FalseType ) const; + + template< typename Arg > + inline void randomize( StrictlyLowerMatrix& matrix, const Arg& min, const Arg& max, TrueType ) const; + + template< typename Arg > + inline void randomize( StrictlyLowerMatrix& 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 Rand< StrictlyLowerMatrix >::generate() const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + StrictlyLowerMatrix 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 + Rand< StrictlyLowerMatrix >::generate( size_t n ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + StrictlyLowerMatrix 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 + Rand< StrictlyLowerMatrix >::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::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + StrictlyLowerMatrix 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 + Rand< StrictlyLowerMatrix >::generate( const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + StrictlyLowerMatrix 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 + Rand< StrictlyLowerMatrix >::generate( size_t n, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + StrictlyLowerMatrix 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 + Rand< StrictlyLowerMatrix >::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::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + StrictlyLowerMatrix 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 >::randomize( StrictlyLowerMatrix& matrix ) const +{ + randomize( matrix, typename IsDenseMatrix::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 >::randomize( StrictlyLowerMatrix& matrix, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=1UL; i(); + } + } +} +/*! \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 >::randomize( StrictlyLowerMatrix& 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( 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 >::randomize( StrictlyLowerMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > StrictlyLowerMatrix::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 dist( n ); + + for( size_t nz=0UL; nz( 1UL, n-1UL ); + if( dist[index] == index ) continue; + ++dist[index]; + ++nz; + } + + for( size_t i=1UL; i() ); + } + 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 >::randomize( StrictlyLowerMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > StrictlyLowerMatrix::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 dist( n-1UL ); + + for( size_t nz=0UL; nz( 0UL, n-2UL ); + if( dist[index] == n - index - 1UL ) continue; + ++dist[index]; + ++nz; + } + + for( size_t j=0UL; j() ); + } + 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 >::randomize( StrictlyLowerMatrix& matrix, + const Arg& min, const Arg& max ) const +{ + randomize( matrix, min, max, typename IsDenseMatrix::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 >::randomize( StrictlyLowerMatrix& matrix, + const Arg& min, const Arg& max, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=1UL; i( 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 >::randomize( StrictlyLowerMatrix& 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( 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 >::randomize( StrictlyLowerMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > StrictlyLowerMatrix::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 dist( n ); + + for( size_t nz=0UL; nz( 1UL, n-1UL ); + if( dist[index] == index ) continue; + ++dist[index]; + ++nz; + } + + for( size_t i=1UL; i( 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 >::randomize( StrictlyLowerMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > StrictlyLowerMatrix::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 dist( n-1UL ); + + for( size_t nz=0UL; nz( 0UL, n-2UL ); + if( dist[index] == n - index - 1UL ) continue; + ++dist[index]; + ++nz; + } + + for( size_t j=0UL; j( 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const StrictlyUpperMatrix generate() const; + inline const StrictlyUpperMatrix generate( size_t n ) const; + inline const StrictlyUpperMatrix generate( size_t n, size_t nonzeros ) const; + + template< typename Arg > + inline const StrictlyUpperMatrix generate( const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const StrictlyUpperMatrix generate( size_t n, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const StrictlyUpperMatrix generate( size_t n, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( StrictlyUpperMatrix& matrix ) const; + inline void randomize( StrictlyUpperMatrix& matrix, size_t nonzeros ) const; + inline void randomize( StrictlyUpperMatrix& matrix, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( StrictlyUpperMatrix& matrix, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( StrictlyUpperMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( StrictlyUpperMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + private: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( StrictlyUpperMatrix& matrix, TrueType ) const; + inline void randomize( StrictlyUpperMatrix& matrix, FalseType ) const; + + template< typename Arg > + inline void randomize( StrictlyUpperMatrix& matrix, const Arg& min, const Arg& max, TrueType ) const; + + template< typename Arg > + inline void randomize( StrictlyUpperMatrix& 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 Rand< StrictlyUpperMatrix >::generate() const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + StrictlyUpperMatrix 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 + Rand< StrictlyUpperMatrix >::generate( size_t n ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + StrictlyUpperMatrix 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 + Rand< StrictlyUpperMatrix >::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::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + StrictlyUpperMatrix 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 + Rand< StrictlyUpperMatrix >::generate( const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + StrictlyUpperMatrix 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 + Rand< StrictlyUpperMatrix >::generate( size_t n, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + StrictlyUpperMatrix 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 + Rand< StrictlyUpperMatrix >::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::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + StrictlyUpperMatrix 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 >::randomize( StrictlyUpperMatrix& matrix ) const +{ + randomize( matrix, typename IsDenseMatrix::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 >::randomize( StrictlyUpperMatrix& matrix, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i(); + } + } +} +/*! \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 >::randomize( StrictlyUpperMatrix& 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( 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 >::randomize( StrictlyUpperMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > StrictlyUpperMatrix::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 dist( n-1UL ); + + for( size_t nz=0UL; nz( 0UL, n-2UL ); + if( dist[index] == n - index - 1UL ) continue; + ++dist[index]; + ++nz; + } + + for( size_t i=0UL; i() ); + } + 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 >::randomize( StrictlyUpperMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > StrictlyUpperMatrix::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 dist( n ); + + for( size_t nz=0UL; nz( 1UL, n-1UL ); + if( dist[index] == index ) continue; + ++dist[index]; + ++nz; + } + + for( size_t j=1UL; j() ); + } + 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 >::randomize( StrictlyUpperMatrix& matrix, + const Arg& min, const Arg& max ) const +{ + randomize( matrix, min, max, typename IsDenseMatrix::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 >::randomize( StrictlyUpperMatrix& matrix, + const Arg& min, const Arg& max, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i( 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 >::randomize( StrictlyUpperMatrix& 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( 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 >::randomize( StrictlyUpperMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > StrictlyUpperMatrix::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 dist( n-1UL ); + + for( size_t nz=0UL; nz( 0UL, n-2UL ); + if( dist[index] == n - index - 1UL ) continue; + ++dist[index]; + ++nz; + } + + for( size_t i=0UL; i( 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 >::randomize( StrictlyUpperMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > StrictlyUpperMatrix::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 dist( n ); + + for( size_t nz=0UL; nz( 1UL, n-1UL ); + if( dist[index] == index ) continue; + ++dist[index]; + ++nz; + } + + for( size_t j=1UL; j( 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 +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( Submatrix& submatrix ) const; + + template< typename Arg > + inline void randomize( Submatrix& 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 >::randomize( Submatrix& submatrix ) const +{ + using blaze::randomize; + + if( SO == rowMajor ) { + for( size_t i=0UL; i // Storage order +template< typename Arg > // Min/max argument type +inline void Rand< Submatrix >::randomize( Submatrix& submatrix, + const Arg& min, const Arg& max ) const +{ + using blaze::randomize; + + if( SO == rowMajor ) { + for( size_t i=0UL; i // Storage order +class Rand< Submatrix > +{ + public: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( Submatrix& submatrix ) const; + inline void randomize( Submatrix& submatrix, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( Submatrix& submatrix, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( Submatrix& 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 >::randomize( Submatrix& submatrix ) const +{ + typedef ElementType_< Submatrix > ElementType; + + const size_t m( submatrix.rows() ); + const size_t n( submatrix.columns() ); + + if( m == 0UL || n == 0UL ) return; + + const size_t nonzeros( rand( 1UL, std::ceil( 0.5*m*n ) ) ); + + submatrix.reset(); + submatrix.reserve( nonzeros ); + + while( submatrix.nonZeros() < nonzeros ) { + submatrix( rand( 0UL, m-1UL ), rand( 0UL, n-1UL ) ) = rand(); + } +} +/*! \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 >::randomize( Submatrix& submatrix, size_t nonzeros ) const +{ + typedef ElementType_< Submatrix > 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( 0UL, m-1UL ), rand( 0UL, n-1UL ) ) = rand(); + } +} +/*! \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 >::randomize( Submatrix& submatrix, + const Arg& min, const Arg& max ) const +{ + typedef ElementType_< Submatrix > ElementType; + + const size_t m( submatrix.rows() ); + const size_t n( submatrix.columns() ); + + if( m == 0UL || n == 0UL ) return; + + const size_t nonzeros( rand( 1UL, std::ceil( 0.5*m*n ) ) ); + + submatrix.reset(); + submatrix.reserve( nonzeros ); + + while( submatrix.nonZeros() < nonzeros ) { + submatrix( rand( 0UL, m-1UL ), rand( 0UL, n-1UL ) ) = rand( 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 >::randomize( Submatrix& submatrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + typedef ElementType_< Submatrix > 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( 0UL, m-1UL ), rand( 0UL, n-1UL ) ) = rand( 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 +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( Subvector& subvector ) const; + + template< typename Arg > + inline void randomize( Subvector& 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 >::randomize( Subvector& subvector ) const +{ + using blaze::randomize; + + for( size_t i=0UL; i // Transpose flag +template< typename Arg > // Min/max argument type +inline void Rand< Subvector >::randomize( Subvector& subvector, + const Arg& min, const Arg& max ) const +{ + using blaze::randomize; + + for( size_t i=0UL; i // Transpose flag +class Rand< Subvector > +{ + public: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( Subvector& subvector ) const; + inline void randomize( Subvector& subvector, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( Subvector& subvector, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( Subvector& 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 >::randomize( Subvector& subvector ) const +{ + typedef ElementType_< Subvector > ElementType; + + const size_t size( subvector.size() ); + + if( size == 0UL ) return; + + const size_t nonzeros( rand( 1UL, std::ceil( 0.5*size ) ) ); + + subvector.reset(); + subvector.reserve( nonzeros ); + + while( subvector.nonZeros() < nonzeros ) { + subvector[ rand( 0UL, size-1UL ) ] = rand(); + } +} +/*! \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 >::randomize( Subvector& subvector, size_t nonzeros ) const +{ + typedef ElementType_< Subvector > 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( 0UL, size-1UL ) ] = rand(); + } +} +/*! \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 >::randomize( Subvector& subvector, + const Arg& min, const Arg& max ) const +{ + typedef ElementType_< Subvector > ElementType; + + const size_t size( subvector.size() ); + + if( size == 0UL ) return; + + const size_t nonzeros( rand( 1UL, std::ceil( 0.5*size ) ) ); + + subvector.reset(); + subvector.reserve( nonzeros ); + + while( subvector.nonZeros() < nonzeros ) { + subvector[ rand( 0UL, size-1UL ) ] = rand( 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 >::randomize( Subvector& subvector, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + typedef ElementType_< Subvector > 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( 0UL, size-1UL ) ] = rand( 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const SymmetricMatrix generate() const; + inline const SymmetricMatrix generate( size_t n ) const; + inline const SymmetricMatrix generate( size_t n, size_t nonzeros ) const; + + template< typename Arg > + inline const SymmetricMatrix generate( const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const SymmetricMatrix generate( size_t n, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const SymmetricMatrix generate( size_t n, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( SymmetricMatrix& matrix ) const; + inline void randomize( SymmetricMatrix& matrix, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( SymmetricMatrix& matrix, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( SymmetricMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + private: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( SymmetricMatrix& matrix, TrueType ) const; + inline void randomize( SymmetricMatrix& matrix, FalseType ) const; + + template< typename Arg > + inline void randomize( SymmetricMatrix& matrix, const Arg& min, const Arg& max, TrueType ) const; + + template< typename Arg > + inline void randomize( SymmetricMatrix& 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 Rand< SymmetricMatrix >::generate() const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + SymmetricMatrix 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 + Rand< SymmetricMatrix >::generate( size_t n ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + SymmetricMatrix 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 + Rand< SymmetricMatrix >::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 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 + Rand< SymmetricMatrix >::generate( const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + SymmetricMatrix 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 + Rand< SymmetricMatrix >::generate( size_t n, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + SymmetricMatrix 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 + Rand< SymmetricMatrix >::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 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 >::randomize( SymmetricMatrix& matrix ) const +{ + randomize( matrix, typename IsDenseMatrix::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 >::randomize( SymmetricMatrix& matrix, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i(); + } + } +} +/*! \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 >::randomize( SymmetricMatrix& 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( 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 >::randomize( SymmetricMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ 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( 0UL, n-1UL ), rand( 0UL, n-1UL ) ) = rand(); + } +} +/*! \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 >::randomize( SymmetricMatrix& matrix, + const Arg& min, const Arg& max ) const +{ + randomize( matrix, min, max, typename IsDenseMatrix::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 >::randomize( SymmetricMatrix& matrix, + const Arg& min, const Arg& max, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i( 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 >::randomize( SymmetricMatrix& 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( 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 >::randomize( SymmetricMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ 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( 0UL, n-1UL ), rand( 0UL, n-1UL ) ) = rand( 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& 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& 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& matrix ) +{ + typedef UnderlyingBuiltin_< ElementType_ > BT; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i(); + } + } + + 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& matrix, const Arg& min, const Arg& max ) +{ + typedef UnderlyingBuiltin_< ElementType_ > BT; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i( 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& matrix ) +{ + typedef UnderlyingBuiltin_< ElementType_ > BT; + + const size_t n( matrix.rows() ); + + makeHermitian( matrix ); + matrix *= matrix; + + for( size_t i=0UL; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const UniLowerMatrix generate() const; + inline const UniLowerMatrix generate( size_t n ) const; + inline const UniLowerMatrix generate( size_t n, size_t nonzeros ) const; + + template< typename Arg > + inline const UniLowerMatrix generate( const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const UniLowerMatrix generate( size_t n, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const UniLowerMatrix generate( size_t n, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( UniLowerMatrix& matrix ) const; + inline void randomize( UniLowerMatrix& matrix, size_t nonzeros ) const; + inline void randomize( UniLowerMatrix& matrix, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( UniLowerMatrix& matrix, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( UniLowerMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( UniLowerMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + private: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( UniLowerMatrix& matrix, TrueType ) const; + inline void randomize( UniLowerMatrix& matrix, FalseType ) const; + + template< typename Arg > + inline void randomize( UniLowerMatrix& matrix, const Arg& min, const Arg& max, TrueType ) const; + + template< typename Arg > + inline void randomize( UniLowerMatrix& 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 Rand< UniLowerMatrix >::generate() const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + UniLowerMatrix 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 + Rand< UniLowerMatrix >::generate( size_t n ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + UniLowerMatrix 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 + Rand< UniLowerMatrix >::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::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + UniLowerMatrix 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 + Rand< UniLowerMatrix >::generate( const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + UniLowerMatrix 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 + Rand< UniLowerMatrix >::generate( size_t n, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + UniLowerMatrix 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 + Rand< UniLowerMatrix >::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::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + UniLowerMatrix 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 >::randomize( UniLowerMatrix& matrix ) const +{ + randomize( matrix, typename IsDenseMatrix::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 >::randomize( UniLowerMatrix& matrix, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=1UL; i(); + } + } +} +/*! \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 >::randomize( UniLowerMatrix& 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( 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 >::randomize( UniLowerMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > UniLowerMatrix::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 dist( n ); + + for( size_t nz=0UL; nz( 1UL, n-1UL ); + if( dist[index] == index ) continue; + ++dist[index]; + ++nz; + } + + for( size_t i=1UL; i() ); + } + 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 >::randomize( UniLowerMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > UniLowerMatrix::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 dist( n-1UL ); + + for( size_t nz=0UL; nz( 0UL, n-2UL ); + if( dist[index] == n - index - 1UL ) continue; + ++dist[index]; + ++nz; + } + + for( size_t j=0UL; j() ); + } + 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 >::randomize( UniLowerMatrix& matrix, + const Arg& min, const Arg& max ) const +{ + randomize( matrix, min, max, typename IsDenseMatrix::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 >::randomize( UniLowerMatrix& matrix, + const Arg& min, const Arg& max, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=1UL; i( 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 >::randomize( UniLowerMatrix& 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( 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 >::randomize( UniLowerMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > UniLowerMatrix::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 dist( n ); + + for( size_t nz=0UL; nz( 1UL, n-1UL ); + if( dist[index] == index ) continue; + ++dist[index]; + ++nz; + } + + for( size_t i=1UL; i( 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 >::randomize( UniLowerMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > UniLowerMatrix::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 dist( n-1UL ); + + for( size_t nz=0UL; nz( 0UL, n-2UL ); + if( dist[index] == n - index - 1UL ) continue; + ++dist[index]; + ++nz; + } + + for( size_t j=0UL; j( 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& 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& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const UniUpperMatrix generate() const; + inline const UniUpperMatrix generate( size_t n ) const; + inline const UniUpperMatrix generate( size_t n, size_t nonzeros ) const; + + template< typename Arg > + inline const UniUpperMatrix generate( const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const UniUpperMatrix generate( size_t n, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const UniUpperMatrix generate( size_t n, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( UniUpperMatrix& matrix ) const; + inline void randomize( UniUpperMatrix& matrix, size_t nonzeros ) const; + inline void randomize( UniUpperMatrix& matrix, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( UniUpperMatrix& matrix, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( UniUpperMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( UniUpperMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + private: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( UniUpperMatrix& matrix, TrueType ) const; + inline void randomize( UniUpperMatrix& matrix, FalseType ) const; + + template< typename Arg > + inline void randomize( UniUpperMatrix& matrix, const Arg& min, const Arg& max, TrueType ) const; + + template< typename Arg > + inline void randomize( UniUpperMatrix& 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 Rand< UniUpperMatrix >::generate() const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + UniUpperMatrix 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 + Rand< UniUpperMatrix >::generate( size_t n ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + UniUpperMatrix 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 + Rand< UniUpperMatrix >::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::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + UniUpperMatrix 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 + Rand< UniUpperMatrix >::generate( const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + UniUpperMatrix 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 + Rand< UniUpperMatrix >::generate( size_t n, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + UniUpperMatrix 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 + Rand< UniUpperMatrix >::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::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + UniUpperMatrix 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 >::randomize( UniUpperMatrix& matrix ) const +{ + randomize( matrix, typename IsDenseMatrix::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 >::randomize( UniUpperMatrix& matrix, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i(); + } + } +} +/*! \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 >::randomize( UniUpperMatrix& 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( 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 >::randomize( UniUpperMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > UniUpperMatrix::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 dist( n-1UL ); + + for( size_t nz=0UL; nz( 0UL, n-2UL ); + if( dist[index] == n - index - 1UL ) continue; + ++dist[index]; + ++nz; + } + + for( size_t i=0UL; i() ); + } + 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 >::randomize( UniUpperMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > UniUpperMatrix::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 dist( n ); + + for( size_t nz=0UL; nz( 1UL, n-1UL ); + if( dist[index] == index ) continue; + ++dist[index]; + ++nz; + } + + for( size_t j=1UL; j() ); + } + 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 >::randomize( UniUpperMatrix& matrix, + const Arg& min, const Arg& max ) const +{ + randomize( matrix, min, max, typename IsDenseMatrix::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 >::randomize( UniUpperMatrix& matrix, + const Arg& min, const Arg& max, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i( 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 >::randomize( UniUpperMatrix& 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( 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 >::randomize( UniUpperMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > UniUpperMatrix::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 dist( n-1UL ); + + for( size_t nz=0UL; nz( 0UL, n-2UL ); + if( dist[index] == n - index - 1UL ) continue; + ++dist[index]; + ++nz; + } + + for( size_t i=0UL; i( 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 >::randomize( UniUpperMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > UniUpperMatrix::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 dist( n ); + + for( size_t nz=0UL; nz( 1UL, n-1UL ); + if( dist[index] == index ) continue; + ++dist[index]; + ++nz; + } + + for( size_t j=1UL; j( 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& 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& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const UpperMatrix generate() const; + inline const UpperMatrix generate( size_t n ) const; + inline const UpperMatrix generate( size_t n, size_t nonzeros ) const; + + template< typename Arg > + inline const UpperMatrix generate( const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const UpperMatrix generate( size_t n, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline const UpperMatrix generate( size_t n, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( UpperMatrix& matrix ) const; + inline void randomize( UpperMatrix& matrix, size_t nonzeros ) const; + inline void randomize( UpperMatrix& matrix, size_t nonzeros ) const; + + template< typename Arg > + inline void randomize( UpperMatrix& matrix, const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( UpperMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + + template< typename Arg > + inline void randomize( UpperMatrix& matrix, size_t nonzeros, + const Arg& min, const Arg& max ) const; + //@} + //********************************************************************************************** + + private: + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( UpperMatrix& matrix, TrueType ) const; + inline void randomize( UpperMatrix& matrix, FalseType ) const; + + template< typename Arg > + inline void randomize( UpperMatrix& matrix, const Arg& min, const Arg& max, TrueType ) const; + + template< typename Arg > + inline void randomize( UpperMatrix& 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 Rand< UpperMatrix >::generate() const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + UpperMatrix 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 + Rand< UpperMatrix >::generate( size_t n ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + UpperMatrix 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 + Rand< UpperMatrix >::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::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + UpperMatrix 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 + Rand< UpperMatrix >::generate( const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + UpperMatrix 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 + Rand< UpperMatrix >::generate( size_t n, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + UpperMatrix 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 + Rand< UpperMatrix >::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::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + UpperMatrix 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 >::randomize( UpperMatrix& matrix ) const +{ + randomize( matrix, typename IsDenseMatrix::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 >::randomize( UpperMatrix& matrix, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i(); + } + } +} +/*! \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 >::randomize( UpperMatrix& 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( 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 >::randomize( UpperMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > UpperMatrix::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + if( n == 0UL ) return; + + matrix.reset(); + matrix.reserve( nonzeros ); + + std::vector dist( n ); + + for( size_t nz=0UL; nz( 0UL, n-1UL ); + if( dist[index] == n - index ) continue; + ++dist[index]; + ++nz; + } + + for( size_t i=0UL; i() ); + } + 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 >::randomize( UpperMatrix& matrix, size_t nonzeros ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > UpperMatrix::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + if( n == 0UL ) return; + + matrix.reset(); + matrix.reserve( nonzeros ); + + std::vector dist( n ); + + for( size_t nz=0UL; nz( 0UL, n-1UL ); + if( dist[index] == index+1UL ) continue; + ++dist[index]; + ++nz; + } + + for( size_t j=0UL; j() ); + } + 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 >::randomize( UpperMatrix& matrix, + const Arg& min, const Arg& max ) const +{ + randomize( matrix, min, max, typename IsDenseMatrix::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 >::randomize( UpperMatrix& matrix, + const Arg& min, const Arg& max, TrueType ) const +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + for( size_t i=0UL; i( 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 >::randomize( UpperMatrix& 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( 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 >::randomize( UpperMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > UpperMatrix::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + if( n == 0UL ) return; + + matrix.reset(); + matrix.reserve( nonzeros ); + + std::vector dist( n ); + + for( size_t nz=0UL; nz( 0UL, n-1UL ); + if( dist[index] == n - index ) continue; + ++dist[index]; + ++nz; + } + + for( size_t i=0UL; i( 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 >::randomize( UpperMatrix& matrix, + size_t nonzeros, const Arg& min, const Arg& max ) const +{ + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( MT ); + + typedef ElementType_ ET; + + const size_t n( matrix.rows() ); + + if( nonzeros > UpperMatrix::maxNonZeros( n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid number of non-zero elements" ); + } + + if( n == 0UL ) return; + + matrix.reset(); + matrix.reserve( nonzeros ); + + std::vector dist( n ); + + for( size_t nz=0UL; nz( 0UL, n-1UL ); + if( dist[index] == index+1UL ) continue; + ++dist[index]; + ++nz; + } + + for( size_t j=0UL; j( 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& matrix ) +{ + const size_t n( matrix.rows() ); + + reset( matrix ); + + for( size_t i=0UL; i >(); + } + + 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& matrix, const Arg& min, const Arg& max ) +{ + typedef ElementType_ Type; + + const size_t n( matrix.rows() ); + + reset( matrix ); + + for( size_t i=0UL; i( 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& matrix ) +{ + typedef UnderlyingBuiltin_< ElementType_ > Type; + + const size_t n( matrix.rows() ); + + reset( matrix ); + + for( size_t i=0UL; i(); + } + + 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& matrix, const Arg& min, const Arg& max ) +{ + typedef UnderlyingBuiltin_< ElementType_ > Type; + + const size_t n( matrix.rows() ); + + reset( matrix ); + + for( size_t i=0UL; i( 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& 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 +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Vector operators */ +//@{ +template< typename T1, typename T2 > +inline const MultTrait_< ElementType_, ElementType_ > + operator,( const Vector& lhs, const Vector& rhs ); + +template< typename T1, typename T2 > +inline const MultTrait_< ElementType_, ElementType_ > + operator,( const Vector& lhs, const Vector& rhs ); + +template< typename T1, typename T2 > +inline const MultTrait_< ElementType_, ElementType_ > + operator,( const Vector& lhs, const Vector& rhs ); + +template< typename T1, typename T2 > +inline const MultTrait_< ElementType_, ElementType_ > + operator,( const Vector& lhs, const Vector& rhs ); + +template< typename T1, typename T2 > +inline const MultTrait_< ElementType_, ElementType_ > + dot( const Vector& lhs, const Vector& rhs ); + +template< typename T1, typename T2 > +inline const MultTrait_< ElementType_, ElementType_ > + dot( const Vector& lhs, const Vector& rhs ); + +template< typename T1, typename T2 > +inline const MultTrait_< ElementType_, ElementType_ > + dot( const Vector& lhs, const Vector& rhs ); + +template< typename T1, typename T2 > +inline const MultTrait_< ElementType_, ElementType_ > + dot( const Vector& lhs, const Vector& rhs ); + +template< typename T1, typename T2 > +inline const MultTrait_< ElementType_, ElementType_ > + outer( const Vector& lhs, const Vector& rhs ); + +template< typename T1, typename T2 > +inline const MultTrait_< ElementType_, ElementType_ > + outer( const Vector& lhs, const Vector& rhs ); + +template< typename T1, typename T2 > +inline const MultTrait_< ElementType_, ElementType_ > + outer( const Vector& lhs, const Vector& rhs ); + +template< typename T1, typename T2 > +inline const MultTrait_< ElementType_, ElementType_ > + outer( const Vector& lhs, const Vector& rhs ); + +template< typename VT, bool TF > +inline std::ostream& operator<<( std::ostream& os, const Vector& 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_, ElementType_ > + operator,( const Vector& lhs, const Vector& 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_, ElementType_ > + operator,( const Vector& lhs, const Vector& 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_, ElementType_ > + operator,( const Vector& lhs, const Vector& 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_, ElementType_ > + operator,( const Vector& lhs, const Vector& 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_, ElementType_ > + dot( const Vector& lhs, const Vector& 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_, ElementType_ > + dot( const Vector& lhs, const Vector& 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_, ElementType_ > + dot( const Vector& lhs, const Vector& 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_, ElementType_ > + dot( const Vector& lhs, const Vector& 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_, ElementType_ > + outer( const Vector& lhs, const Vector& 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_, ElementType_ > + outer( const Vector& lhs, const Vector& 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_, ElementType_ > + outer( const Vector& lhs, const Vector& 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_, ElementType_ > + outer( const Vector& lhs, const Vector& 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& v ) +{ + CompositeType_ tmp( ~v ); + + if( tmp.size() == 0UL ) { + os << "( )\n"; + } + else if( TF == rowVector ) { + os << "("; + for( size_t i=0UL; i +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// DIAGONALMATRIX OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name DiagonalMatrix operators */ +//@{ +template< typename MT, bool SO, bool DF > +inline void reset( DiagonalMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void reset( DiagonalMatrix& m, size_t i ); + +template< typename MT, bool SO, bool DF > +inline void clear( DiagonalMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isDefault( const DiagonalMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isIntact( const DiagonalMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void swap( DiagonalMatrix& a, DiagonalMatrix& 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& 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& 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& 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 > 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& 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 > 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& 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& a, DiagonalMatrix& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 2UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 2UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 3UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 3UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 4UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 4UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 5UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 5UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 6UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 6UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + MT& A( derestrict( m ) ); + + for( size_t i=0UL; i +inline void lu( const DiagonalMatrix& A, DenseMatrix& L, + DenseMatrix& U, Matrix& P ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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_ ET3; + typedef ElementType_ ET4; + + const size_t n( (~A).rows() ); + + DerestrictTrait_ U2( derestrict( ~U ) ); + + (~L) = A; + + resize( ~U, n, n ); + reset( U2 ); + + resize( ~P, n, n ); + reset( ~P ); + + for( size_t i=0UL; i // Type of the right-hand side dense vector +inline bool tryAssign( const DiagonalMatrix& lhs, + const DenseVector& 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 // Type of the right-hand side dense vector +inline bool tryAssign( const DiagonalMatrix& lhs, + const DenseVector& 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 // Type of the right-hand side sparse vector +inline bool tryAssign( const DiagonalMatrix& lhs, + const SparseVector& 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& lhs, + const SparseVector& 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& lhs, + const DenseMatrix& 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 // Type of the right-hand side dense matrix +inline bool tryAssign( const DiagonalMatrix& lhs, + const DenseMatrix& 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 // Type of the right-hand side sparse matrix +inline bool tryAssign( const DiagonalMatrix& lhs, + const SparseMatrix& 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; iindex() ) && !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& lhs, + const SparseMatrix& 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; jindex() ) && !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& lhs, + const Vector& 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& lhs, + const Matrix& 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& lhs, + const Vector& 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& lhs, + const Matrix& 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& m ) +{ + return m.matrix_; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Rows< DiagonalMatrix > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Columns< DiagonalMatrix > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSQUARE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsSquare< DiagonalMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsSymmetric< DiagonalMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsHermitian< DiagonalMatrix > + : public BoolConstant< IsBuiltin< ElementType_ >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsLower< DiagonalMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsUpper< DiagonalMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAdaptor< DiagonalMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESTRICTED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsRestricted< DiagonalMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct HasConstDataAccess< DiagonalMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAligned< DiagonalMatrix > : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsPadded< DiagonalMatrix > : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsResizable< DiagonalMatrix > : public BoolConstant< IsResizable::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// REMOVEADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RemoveAdaptor< DiagonalMatrix > +{ + using Type = MT; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DERESTRICTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct DerestrictTrait< DiagonalMatrix > +{ + 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, StaticMatrix > +{ + using Type = AddTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< StaticMatrix, DiagonalMatrix > +{ + using Type = AddTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct AddTrait< DiagonalMatrix, HybridMatrix > +{ + using Type = AddTrait< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< HybridMatrix, DiagonalMatrix > +{ + using Type = AddTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< DiagonalMatrix, DynamicMatrix > +{ + using Type = AddTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< DynamicMatrix, DiagonalMatrix > +{ + using Type = AddTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct AddTrait< DiagonalMatrix, CustomMatrix > +{ + using Type = AddTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CustomMatrix, DiagonalMatrix > +{ + using Type = AddTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< DiagonalMatrix, CompressedMatrix > +{ + using Type = AddTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CompressedMatrix, DiagonalMatrix > +{ + using Type = AddTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct AddTrait< DiagonalMatrix, SymmetricMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct AddTrait< SymmetricMatrix, DiagonalMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< DiagonalMatrix, HermitianMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< HermitianMatrix, DiagonalMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< DiagonalMatrix, LowerMatrix > +{ + using Type = LowerMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< LowerMatrix, DiagonalMatrix > +{ + using Type = LowerMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< DiagonalMatrix, UniLowerMatrix > +{ + using Type = LowerMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniLowerMatrix, DiagonalMatrix > +{ + using Type = LowerMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< DiagonalMatrix, StrictlyLowerMatrix > +{ + using Type = LowerMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyLowerMatrix, DiagonalMatrix > +{ + using Type = LowerMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< DiagonalMatrix, UpperMatrix > +{ + using Type = UpperMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UpperMatrix, DiagonalMatrix > +{ + using Type = UpperMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< DiagonalMatrix, UniUpperMatrix > +{ + using Type = UpperMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniUpperMatrix, DiagonalMatrix > +{ + using Type = UpperMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< DiagonalMatrix, StrictlyUpperMatrix > +{ + using Type = UpperMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyUpperMatrix, DiagonalMatrix > +{ + using Type = UpperMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< DiagonalMatrix, DiagonalMatrix > +{ + using Type = DiagonalMatrix< AddTrait_ >; +}; +/*! \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, StaticMatrix > +{ + using Type = SubTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< StaticMatrix, DiagonalMatrix > +{ + using Type = SubTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct SubTrait< DiagonalMatrix, HybridMatrix > +{ + using Type = SubTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< HybridMatrix, DiagonalMatrix > +{ + using Type = SubTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< DiagonalMatrix, DynamicMatrix > +{ + using Type = SubTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< DynamicMatrix, DiagonalMatrix > +{ + using Type = SubTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct SubTrait< DiagonalMatrix, CustomMatrix > +{ + using Type = SubTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CustomMatrix, DiagonalMatrix > +{ + using Type = SubTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< DiagonalMatrix, CompressedMatrix > +{ + using Type = SubTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CompressedMatrix, DiagonalMatrix > +{ + using Type = SubTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct SubTrait< DiagonalMatrix, SymmetricMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct SubTrait< SymmetricMatrix, DiagonalMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< DiagonalMatrix, HermitianMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< HermitianMatrix, DiagonalMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< DiagonalMatrix, LowerMatrix > +{ + using Type = LowerMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< LowerMatrix, DiagonalMatrix > +{ + using Type = LowerMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< DiagonalMatrix, UniLowerMatrix > +{ + using Type = LowerMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniLowerMatrix, DiagonalMatrix > +{ + using Type = LowerMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< DiagonalMatrix, UpperMatrix > +{ + using Type = UpperMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UpperMatrix, DiagonalMatrix > +{ + using Type = UpperMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< DiagonalMatrix, UniUpperMatrix > +{ + using Type = UpperMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniUpperMatrix, DiagonalMatrix > +{ + using Type = UpperMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< DiagonalMatrix, StrictlyUpperMatrix > +{ + using Type = UpperMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyUpperMatrix, DiagonalMatrix > +{ + using Type = UpperMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< DiagonalMatrix, DiagonalMatrix > +{ + using Type = DiagonalMatrix< SubTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< DiagonalMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = DiagonalMatrix< MultTrait_ >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< T, DiagonalMatrix, EnableIf_< IsNumeric > > +{ + using Type = DiagonalMatrix< MultTrait_ >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< DiagonalMatrix, StaticVector > +{ + using Type = MultTrait_< MT, StaticVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< StaticVector, DiagonalMatrix > +{ + using Type = MultTrait_< StaticVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< DiagonalMatrix, HybridVector > +{ + using Type = MultTrait_< MT, HybridVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< HybridVector, DiagonalMatrix > +{ + using Type = MultTrait_< HybridVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< DiagonalMatrix, DynamicVector > +{ + using Type = MultTrait_< MT, DynamicVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< DynamicVector, DiagonalMatrix > +{ + using Type = MultTrait_< DynamicVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF > +struct MultTrait< DiagonalMatrix, CustomVector > +{ + using Type = MultTrait_< MT, CustomVector >; +}; + +template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF > +struct MultTrait< CustomVector, DiagonalMatrix > +{ + using Type = MultTrait_< CustomVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< DiagonalMatrix, CompressedVector > +{ + using Type = MultTrait_< MT, CompressedVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< CompressedVector, DiagonalMatrix > +{ + using Type = MultTrait_< CompressedVector, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< DiagonalMatrix, StaticMatrix > +{ + using Type = MultTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< StaticMatrix, DiagonalMatrix > +{ + using Type = MultTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< DiagonalMatrix, HybridMatrix > +{ + using Type = MultTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< HybridMatrix, DiagonalMatrix > +{ + using Type = MultTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< DiagonalMatrix, DynamicMatrix > +{ + using Type = MultTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< DynamicMatrix, DiagonalMatrix > +{ + using Type = MultTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct MultTrait< DiagonalMatrix, CustomMatrix > +{ + using Type = MultTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CustomMatrix, DiagonalMatrix > +{ + using Type = MultTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< DiagonalMatrix, CompressedMatrix > +{ + using Type = MultTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CompressedMatrix, DiagonalMatrix > +{ + using Type = MultTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct MultTrait< DiagonalMatrix, SymmetricMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct MultTrait< SymmetricMatrix, DiagonalMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< DiagonalMatrix, HermitianMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< HermitianMatrix, DiagonalMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< DiagonalMatrix, LowerMatrix > +{ + using Type = LowerMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< LowerMatrix, DiagonalMatrix > +{ + using Type = LowerMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< DiagonalMatrix, UniLowerMatrix > +{ + using Type = LowerMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniLowerMatrix, DiagonalMatrix > +{ + using Type = LowerMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< DiagonalMatrix, StrictlyLowerMatrix > +{ + using Type = StrictlyLowerMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyLowerMatrix, DiagonalMatrix > +{ + using Type = StrictlyLowerMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< DiagonalMatrix, UpperMatrix > +{ + using Type = UpperMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UpperMatrix, DiagonalMatrix > +{ + using Type = UpperMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< DiagonalMatrix, UniUpperMatrix > +{ + using Type = UpperMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniUpperMatrix, DiagonalMatrix > +{ + using Type = UpperMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< DiagonalMatrix, StrictlyUpperMatrix > +{ + using Type = StrictlyUpperMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyUpperMatrix, DiagonalMatrix > +{ + using Type = StrictlyUpperMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< DiagonalMatrix, DiagonalMatrix > +{ + using Type = DiagonalMatrix< MultTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct DivTrait< DiagonalMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = DiagonalMatrix< DivTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// FOREACHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Abs > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Floor > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Ceil > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Conj > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Real > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Imag > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Sin > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Asin > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Sinh > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Asinh > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Tan > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Atan > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Tanh > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Atanh > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< DiagonalMatrix, Erf > +{ + using Type = DiagonalMatrix< ForEachTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MATHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MathTrait< DiagonalMatrix, DiagonalMatrix > +{ + using HighType = DiagonalMatrix< typename MathTrait::HighType >; + using LowType = DiagonalMatrix< typename MathTrait::LowType >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct SubmatrixTrait< DiagonalMatrix > +{ + using Type = SubmatrixTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RowTrait< DiagonalMatrix > +{ + using Type = RowTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct ColumnTrait< DiagonalMatrix > +{ + using Type = ColumnTrait_; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// HERMITIANMATRIX OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name HermitianMatrix operators */ +//@{ +template< typename MT, bool SO, bool DF > +inline void reset( HermitianMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void reset( HermitianMatrix& m, size_t i ); + +template< typename MT, bool SO, bool DF > +inline void clear( HermitianMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isDefault( const HermitianMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isIntact( const HermitianMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void swap( HermitianMatrix& a, HermitianMatrix& 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& 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& 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& 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 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& 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 > 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& 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& a, HermitianMatrix& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 2UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 2UL, "Invalid number of columns detected" ); + + typedef ElementType_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 3UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 3UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 4UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 4UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 5UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 5UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 6UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 6UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix 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 or \c complex 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& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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& lhs, + const Vector& 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 > ET; + + return ( IsBuiltin::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& lhs, + const Vector& 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 > ET; + + return ( IsBuiltin::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& lhs, + const Matrix& 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& lhs, + const Vector& 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& lhs, + const Matrix& 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& lhs, + const Vector& 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& lhs, + const Matrix& 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& lhs, + const Vector& 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& lhs, + const Vector& 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 > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Columns< HermitianMatrix > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSQUARE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsSquare< HermitianMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsSymmetric< HermitianMatrix > + : public BoolConstant< IsBuiltin< ElementType_ >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsHermitian< HermitianMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAdaptor< HermitianMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESTRICTED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsRestricted< HermitianMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct HasConstDataAccess< HermitianMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAligned< HermitianMatrix > : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsPadded< HermitianMatrix > : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsResizable< HermitianMatrix > : public BoolConstant< IsResizable::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// REMOVEADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RemoveAdaptor< HermitianMatrix > +{ + 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, StaticMatrix > +{ + using Type = AddTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< StaticMatrix, HermitianMatrix > +{ + using Type = AddTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct AddTrait< HermitianMatrix, HybridMatrix > +{ + using Type = AddTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< HybridMatrix, HermitianMatrix > +{ + using Type = AddTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< HermitianMatrix, DynamicMatrix > +{ + using Type = AddTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< DynamicMatrix, HermitianMatrix > +{ + using Type = AddTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct AddTrait< HermitianMatrix, CustomMatrix > +{ + using Type = AddTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CustomMatrix, HermitianMatrix > +{ + using Type = AddTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< HermitianMatrix, CompressedMatrix > +{ + using Type = AddTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CompressedMatrix, HermitianMatrix > +{ + using Type = AddTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct AddTrait< HermitianMatrix, SymmetricMatrix > +{ + using Type = If_< IsSymmetric< HermitianMatrix > + , SymmetricMatrix< AddTrait_ > + , AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< SymmetricMatrix, HermitianMatrix > +{ + using Type = If_< IsSymmetric< HermitianMatrix > + , SymmetricMatrix< AddTrait_ > + , AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< HermitianMatrix, HermitianMatrix > +{ + using Type = HermitianMatrix< AddTrait_ >; +}; +/*! \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, StaticMatrix > +{ + using Type = SubTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< StaticMatrix, HermitianMatrix > +{ + using Type = SubTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct SubTrait< HermitianMatrix, HybridMatrix > +{ + using Type = SubTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< HybridMatrix, HermitianMatrix > +{ + using Type = SubTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< HermitianMatrix, DynamicMatrix > +{ + using Type = SubTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< DynamicMatrix, HermitianMatrix > +{ + using Type = SubTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct SubTrait< HermitianMatrix, CustomMatrix > +{ + using Type = SubTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CustomMatrix, HermitianMatrix > +{ + using Type = SubTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< HermitianMatrix, CompressedMatrix > +{ + using Type = SubTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CompressedMatrix, HermitianMatrix > +{ + using Type = SubTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< HermitianMatrix, SymmetricMatrix > +{ + using Type = If_< IsSymmetric< HermitianMatrix > + , SymmetricMatrix< SubTrait_ > + , SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< SymmetricMatrix, HermitianMatrix > +{ + using Type = If_< IsSymmetric< HermitianMatrix > + , SymmetricMatrix< SubTrait_ > + , SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< HermitianMatrix, HermitianMatrix > +{ + using Type = HermitianMatrix< SubTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< HermitianMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = HermitianMatrix< MultTrait_ >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< T, HermitianMatrix, EnableIf_< IsNumeric > > +{ + using Type = HermitianMatrix< MultTrait_ >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< HermitianMatrix, StaticVector > +{ + using Type = MultTrait_< MT, StaticVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< StaticVector, HermitianMatrix > +{ + using Type = MultTrait_< StaticVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< HermitianMatrix, HybridVector > +{ + using Type = MultTrait_< MT, HybridVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< HybridVector, HermitianMatrix > +{ + using Type = MultTrait_< HybridVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< HermitianMatrix, DynamicVector > +{ + using Type = MultTrait_< MT, DynamicVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< DynamicVector, HermitianMatrix > +{ + using Type = MultTrait_< DynamicVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF > +struct MultTrait< HermitianMatrix, CustomVector > +{ + using Type = MultTrait_< MT, CustomVector >; +}; + +template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF > +struct MultTrait< CustomVector, HermitianMatrix > +{ + using Type = MultTrait_< CustomVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< HermitianMatrix, CompressedVector > +{ + using Type = MultTrait_< MT, CompressedVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< CompressedVector, HermitianMatrix > +{ + using Type = MultTrait_< CompressedVector, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< HermitianMatrix, StaticMatrix > +{ + using Type = MultTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< StaticMatrix, HermitianMatrix > +{ + using Type = MultTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< HermitianMatrix, HybridMatrix > +{ + using Type = MultTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< HybridMatrix, HermitianMatrix > +{ + using Type = MultTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< HermitianMatrix, DynamicMatrix > +{ + using Type = MultTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< DynamicMatrix, HermitianMatrix > +{ + using Type = MultTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct MultTrait< HermitianMatrix, CustomMatrix > +{ + using Type = MultTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CustomMatrix, HermitianMatrix > +{ + using Type = MultTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< HermitianMatrix, CompressedMatrix > +{ + using Type = MultTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CompressedMatrix, HermitianMatrix > +{ + using Type = MultTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< HermitianMatrix, SymmetricMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< SymmetricMatrix, HermitianMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< HermitianMatrix, HermitianMatrix > +{ + using Type = MultTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct DivTrait< HermitianMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = HermitianMatrix< DivTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// FOREACHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Abs > +{ + using Type = HermitianMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Floor > +{ + using Type = HermitianMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Ceil > +{ + using Type = HermitianMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Conj > +{ + using Type = HermitianMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Real > +{ + using Type = HermitianMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Imag > +{ + using Type = If_< IsBuiltin< ElementType_ > + , HermitianMatrix< ForEachTrait_ > + , ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Sqrt > +{ + using Type = HermitianMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, InvSqrt > +{ + using Type = HermitianMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Cbrt > +{ + using Type = HermitianMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, InvCbrt > +{ + using Type = HermitianMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, typename ET > +struct ForEachTrait< HermitianMatrix, Pow > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Pow > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Exp > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Exp > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Log > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Log > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Log10 > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Log10 > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Sin > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Sin > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Asin > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Asin > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Sinh > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Sinh > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Asinh > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Asinh > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Cos > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Cos > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Acos > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Acos > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Cosh > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Cosh > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Acosh > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Acosh > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Tan > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Tan > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Atan > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Atan > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Tanh > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Tanh > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Atanh > +{ + using Type = HermitianMatrix< ForEachTrait_< MT, Atanh > >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Erf > +{ + using Type = HermitianMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< HermitianMatrix, Erfc > +{ + using Type = HermitianMatrix< ForEachTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MATHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MathTrait< HermitianMatrix, HermitianMatrix > +{ + using HighType = HermitianMatrix< typename MathTrait::HighType >; + using LowType = HermitianMatrix< typename MathTrait::LowType >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct SubmatrixTrait< HermitianMatrix > +{ + using Type = SubmatrixTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RowTrait< HermitianMatrix > +{ + using Type = RowTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct ColumnTrait< HermitianMatrix > +{ + using Type = ColumnTrait_; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// LOWERMATRIX OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LowerMatrix operators */ +//@{ +template< typename MT, bool SO, bool DF > +inline void reset( LowerMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void reset( LowerMatrix& m, size_t i ); + +template< typename MT, bool SO, bool DF > +inline void clear( LowerMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isDefault( const LowerMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isIntact( const LowerMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void swap( LowerMatrix& a, LowerMatrix& 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& 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& 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& 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 > 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& 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 > 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& 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& a, LowerMatrix& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 2UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 2UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 3UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 3UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 4UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 4UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 5UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 5UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 6UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 6UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + DerestrictTrait_ 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 or \c complex 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& 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 or \c complex 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& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( isDiagonal( ~m ), "Violation of preconditions detected" ); + + DerestrictTrait_ A( derestrict( ~m ) ); + + for( size_t i=0UL; i +inline void lu( const LowerMatrix& A, DenseMatrix& L, + DenseMatrix& U, Matrix& P ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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_ ET3; + typedef ElementType_ ET4; + + const size_t n( (~A).rows() ); + + DerestrictTrait_ U2( derestrict( ~U ) ); + + (~L) = A; + + resize( ~U, n, n ); + reset( U2 ); + + resize( ~P, n, n ); + reset( ~P ); + + for( size_t i=0UL; i // Type of the right-hand side dense vector +inline bool tryAssign( const LowerMatrix& lhs, + const DenseVector& 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 // Type of the right-hand side dense vector +inline bool tryAssign( const LowerMatrix& lhs, + const DenseVector& 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& lhs, + const SparseVector& 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& lhs, + const SparseVector& 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& lhs, + const DenseMatrix& 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= column ); + const size_t jbegin( ( containsDiagonal )?( row + i - column + 1UL ):( 0UL ) ); + + for( size_t j=jbegin; j // Type of the right-hand side dense matrix +inline bool tryAssign( const LowerMatrix& lhs, + const DenseMatrix& 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 // Type of the right-hand side sparse matrix +inline bool tryAssign( const LowerMatrix& lhs, + const SparseMatrix& 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= 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& lhs, + const SparseMatrix& 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; jvalue() ) ) + 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& lhs, + const Vector& 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& lhs, + const Matrix& 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& lhs, + const Vector& 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& lhs, + const Matrix& 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& m ) +{ + return m.matrix_; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Rows< LowerMatrix > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Columns< LowerMatrix > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSQUARE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsSquare< LowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsLower< LowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAdaptor< LowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESTRICTED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsRestricted< LowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct HasConstDataAccess< LowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAligned< LowerMatrix > : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsPadded< LowerMatrix > : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsResizable< LowerMatrix > : public BoolConstant< IsResizable::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// REMOVEADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RemoveAdaptor< LowerMatrix > +{ + using Type = MT; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DERESTRICTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct DerestrictTrait< LowerMatrix > +{ + 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, StaticMatrix > +{ + using Type = AddTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< StaticMatrix, LowerMatrix > +{ + using Type = AddTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct AddTrait< LowerMatrix, HybridMatrix > +{ + using Type = AddTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< HybridMatrix, LowerMatrix > +{ + using Type = AddTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< LowerMatrix, DynamicMatrix > +{ + using Type = AddTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< DynamicMatrix, LowerMatrix > +{ + using Type = AddTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct AddTrait< LowerMatrix, CustomMatrix > +{ + using Type = AddTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CustomMatrix, LowerMatrix > +{ + using Type = AddTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< LowerMatrix, CompressedMatrix > +{ + using Type = AddTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CompressedMatrix, LowerMatrix > +{ + using Type = AddTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct AddTrait< LowerMatrix, SymmetricMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct AddTrait< SymmetricMatrix, LowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< LowerMatrix, HermitianMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< HermitianMatrix, LowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< LowerMatrix, LowerMatrix > +{ + using Type = LowerMatrix< AddTrait_ >; +}; +/*! \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, StaticMatrix > +{ + using Type = SubTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< StaticMatrix, LowerMatrix > +{ + using Type = SubTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct SubTrait< LowerMatrix, HybridMatrix > +{ + using Type = SubTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< HybridMatrix, LowerMatrix > +{ + using Type = SubTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< LowerMatrix, DynamicMatrix > +{ + using Type = SubTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< DynamicMatrix, LowerMatrix > +{ + using Type = SubTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct SubTrait< LowerMatrix, CustomMatrix > +{ + using Type = SubTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CustomMatrix, LowerMatrix > +{ + using Type = SubTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< LowerMatrix, CompressedMatrix > +{ + using Type = SubTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CompressedMatrix, LowerMatrix > +{ + using Type = SubTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct SubTrait< LowerMatrix, SymmetricMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct SubTrait< SymmetricMatrix, LowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< LowerMatrix, HermitianMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< HermitianMatrix, LowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< LowerMatrix, LowerMatrix > +{ + using Type = LowerMatrix< SubTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< LowerMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = LowerMatrix< MultTrait_ >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< T, LowerMatrix, EnableIf_< IsNumeric > > +{ + using Type = LowerMatrix< MultTrait_ >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< LowerMatrix, StaticVector > +{ + using Type = MultTrait_< MT, StaticVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< StaticVector, LowerMatrix > +{ + using Type = MultTrait_< StaticVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< LowerMatrix, HybridVector > +{ + using Type = MultTrait_< MT, HybridVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< HybridVector, LowerMatrix > +{ + using Type = MultTrait_< HybridVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< LowerMatrix, DynamicVector > +{ + using Type = MultTrait_< MT, DynamicVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< DynamicVector, LowerMatrix > +{ + using Type = MultTrait_< DynamicVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF > +struct MultTrait< LowerMatrix, CustomVector > +{ + using Type = MultTrait_< MT, CustomVector >; +}; + +template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF > +struct MultTrait< CustomVector, LowerMatrix > +{ + using Type = MultTrait_< CustomVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< LowerMatrix, CompressedVector > +{ + using Type = MultTrait_< MT, CompressedVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< CompressedVector, LowerMatrix > +{ + using Type = MultTrait_< CompressedVector, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< LowerMatrix, StaticMatrix > +{ + using Type = MultTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< StaticMatrix, LowerMatrix > +{ + using Type = MultTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< LowerMatrix, HybridMatrix > +{ + using Type = MultTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< HybridMatrix, LowerMatrix > +{ + using Type = MultTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< LowerMatrix, DynamicMatrix > +{ + using Type = MultTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< DynamicMatrix, LowerMatrix > +{ + using Type = MultTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct MultTrait< LowerMatrix, CustomMatrix > +{ + using Type = MultTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CustomMatrix, LowerMatrix > +{ + using Type = MultTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< LowerMatrix, CompressedMatrix > +{ + using Type = MultTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CompressedMatrix, LowerMatrix > +{ + using Type = MultTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct MultTrait< LowerMatrix, SymmetricMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct MultTrait< SymmetricMatrix, LowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< LowerMatrix, HermitianMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< HermitianMatrix, LowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< LowerMatrix, LowerMatrix > +{ + using Type = LowerMatrix< MultTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct DivTrait< LowerMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = LowerMatrix< DivTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// FOREACHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Abs > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Floor > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Ceil > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Conj > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Real > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Imag > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Sin > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Asin > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Sinh > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Asinh > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Tan > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Atan > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Tanh > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Atanh > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< LowerMatrix, Erf > +{ + using Type = LowerMatrix< ForEachTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MATHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MathTrait< LowerMatrix, LowerMatrix > +{ + using HighType = LowerMatrix< typename MathTrait::HighType >; + using LowType = LowerMatrix< typename MathTrait::LowType >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct SubmatrixTrait< LowerMatrix > +{ + using Type = SubmatrixTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RowTrait< LowerMatrix > +{ + using Type = RowTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct ColumnTrait< LowerMatrix > +{ + using Type = ColumnTrait_; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// STRICTLYLOWERMATRIX OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name StrictlyLowerMatrix operators */ +//@{ +template< typename MT, bool SO, bool DF > +inline void reset( StrictlyLowerMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void reset( StrictlyLowerMatrix& m, size_t i ); + +template< typename MT, bool SO, bool DF > +inline void clear( StrictlyLowerMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isDefault( const StrictlyLowerMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isIntact( const StrictlyLowerMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void swap( StrictlyLowerMatrix& a, StrictlyLowerMatrix& 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& 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& 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& 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& 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& 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 > 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& m ) +{ + return isDefault_backend( m, typename IsResizable::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 > 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& 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& a, StrictlyLowerMatrix& 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& lhs, + const DenseVector& 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 // Type of the right-hand side dense vector +inline bool tryAssign( const StrictlyLowerMatrix& lhs, + const DenseVector& 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& lhs, + const SparseVector& 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& lhs, + const SparseVector& 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& lhs, + const DenseMatrix& 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= column ); + const size_t jbegin( ( containsDiagonal )?( row + i - column ):( 0UL ) ); + + for( size_t j=jbegin; j // Type of the right-hand side dense matrix +inline bool tryAssign( const StrictlyLowerMatrix& lhs, + const DenseMatrix& 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 // Type of the right-hand side sparse matrix +inline bool tryAssign( const StrictlyLowerMatrix& lhs, + const SparseMatrix& 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= 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& lhs, + const SparseMatrix& 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; jvalue() ) ) + 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& lhs, + const Vector& 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& lhs, + const Matrix& 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& lhs, + const Vector& 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& lhs, + const Matrix& 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& m ) +{ + return m.matrix_; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Rows< StrictlyLowerMatrix > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Columns< StrictlyLowerMatrix > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSQUARE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsSquare< StrictlyLowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsStrictlyLower< StrictlyLowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAdaptor< StrictlyLowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESTRICTED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsRestricted< StrictlyLowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct HasConstDataAccess< StrictlyLowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAligned< StrictlyLowerMatrix > : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsPadded< StrictlyLowerMatrix > : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsResizable< StrictlyLowerMatrix > : public BoolConstant< IsResizable::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// REMOVEADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RemoveAdaptor< StrictlyLowerMatrix > +{ + using Type = MT; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DERESTRICTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct DerestrictTrait< StrictlyLowerMatrix > +{ + 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, StaticMatrix > +{ + using Type = AddTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< StaticMatrix, StrictlyLowerMatrix > +{ + using Type = AddTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct AddTrait< StrictlyLowerMatrix, HybridMatrix > +{ + using Type = AddTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< HybridMatrix, StrictlyLowerMatrix > +{ + using Type = AddTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< StrictlyLowerMatrix, DynamicMatrix > +{ + using Type = AddTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< DynamicMatrix, StrictlyLowerMatrix > +{ + using Type = AddTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct AddTrait< StrictlyLowerMatrix, CustomMatrix > +{ + using Type = AddTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CustomMatrix, StrictlyLowerMatrix > +{ + using Type = AddTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< StrictlyLowerMatrix, CompressedMatrix > +{ + using Type = AddTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CompressedMatrix, StrictlyLowerMatrix > +{ + using Type = AddTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct AddTrait< StrictlyLowerMatrix, SymmetricMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct AddTrait< SymmetricMatrix, StrictlyLowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyLowerMatrix, HermitianMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< HermitianMatrix, StrictlyLowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyLowerMatrix, LowerMatrix > +{ + using Type = LowerMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< LowerMatrix, StrictlyLowerMatrix > +{ + using Type = LowerMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyLowerMatrix, UniLowerMatrix > +{ + using Type = UniLowerMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniLowerMatrix, StrictlyLowerMatrix > +{ + using Type = UniLowerMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyLowerMatrix, StrictlyLowerMatrix > +{ + using Type = StrictlyLowerMatrix< AddTrait_ >; +}; +/*! \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, StaticMatrix > +{ + using Type = SubTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< StaticMatrix, StrictlyLowerMatrix > +{ + using Type = SubTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct SubTrait< StrictlyLowerMatrix, HybridMatrix > +{ + using Type = SubTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< HybridMatrix, StrictlyLowerMatrix > +{ + using Type = SubTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< StrictlyLowerMatrix, DynamicMatrix > +{ + using Type = SubTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< DynamicMatrix, StrictlyLowerMatrix > +{ + using Type = SubTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct SubTrait< StrictlyLowerMatrix, CustomMatrix > +{ + using Type = SubTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CustomMatrix, StrictlyLowerMatrix > +{ + using Type = SubTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< StrictlyLowerMatrix, CompressedMatrix > +{ + using Type = SubTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CompressedMatrix, StrictlyLowerMatrix > +{ + using Type = SubTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct SubTrait< StrictlyLowerMatrix, SymmetricMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct SubTrait< SymmetricMatrix, StrictlyLowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyLowerMatrix, HermitianMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< HermitianMatrix, StrictlyLowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyLowerMatrix, LowerMatrix > +{ + using Type = LowerMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< LowerMatrix, StrictlyLowerMatrix > +{ + using Type = LowerMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyLowerMatrix, UniLowerMatrix > +{ + using Type = LowerMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniLowerMatrix, StrictlyLowerMatrix > +{ + using Type = UniLowerMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyLowerMatrix, StrictlyLowerMatrix > +{ + using Type = StrictlyLowerMatrix< SubTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< StrictlyLowerMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = StrictlyLowerMatrix< MultTrait_ >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< T, StrictlyLowerMatrix, EnableIf_< IsNumeric > > +{ + using Type = StrictlyLowerMatrix< MultTrait_ >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< StrictlyLowerMatrix, StaticVector > +{ + using Type = MultTrait_< MT, StaticVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< StaticVector, StrictlyLowerMatrix > +{ + using Type = MultTrait_< StaticVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< StrictlyLowerMatrix, HybridVector > +{ + using Type = MultTrait_< MT, HybridVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< HybridVector, StrictlyLowerMatrix > +{ + using Type = MultTrait_< HybridVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< StrictlyLowerMatrix, DynamicVector > +{ + using Type = MultTrait_< MT, DynamicVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< DynamicVector, StrictlyLowerMatrix > +{ + using Type = MultTrait_< DynamicVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF > +struct MultTrait< StrictlyLowerMatrix, CustomVector > +{ + using Type = MultTrait_< MT, CustomVector >; +}; + +template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF > +struct MultTrait< CustomVector, StrictlyLowerMatrix > +{ + using Type = MultTrait_< CustomVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< StrictlyLowerMatrix, CompressedVector > +{ + using Type = MultTrait_< MT, CompressedVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< CompressedVector, StrictlyLowerMatrix > +{ + using Type = MultTrait_< CompressedVector, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< StrictlyLowerMatrix, StaticMatrix > +{ + using Type = MultTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< StaticMatrix, StrictlyLowerMatrix > +{ + using Type = MultTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< StrictlyLowerMatrix, HybridMatrix > +{ + using Type = MultTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< HybridMatrix, StrictlyLowerMatrix > +{ + using Type = MultTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< StrictlyLowerMatrix, DynamicMatrix > +{ + using Type = MultTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< DynamicMatrix, StrictlyLowerMatrix > +{ + using Type = MultTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct MultTrait< StrictlyLowerMatrix, CustomMatrix > +{ + using Type = MultTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CustomMatrix, StrictlyLowerMatrix > +{ + using Type = MultTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< StrictlyLowerMatrix, CompressedMatrix > +{ + using Type = MultTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CompressedMatrix, StrictlyLowerMatrix > +{ + using Type = MultTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct MultTrait< StrictlyLowerMatrix, SymmetricMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct MultTrait< SymmetricMatrix, StrictlyLowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyLowerMatrix, HermitianMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< HermitianMatrix, StrictlyLowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyLowerMatrix, LowerMatrix > +{ + using Type = StrictlyLowerMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< LowerMatrix, StrictlyLowerMatrix > +{ + using Type = StrictlyLowerMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyLowerMatrix, UniLowerMatrix > +{ + using Type = StrictlyLowerMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniLowerMatrix, StrictlyLowerMatrix > +{ + using Type = StrictlyLowerMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyLowerMatrix, StrictlyLowerMatrix > +{ + using Type = StrictlyLowerMatrix< MultTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct DivTrait< StrictlyLowerMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = StrictlyLowerMatrix< DivTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// FOREACHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Abs > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Floor > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Ceil > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Conj > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Real > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Imag > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Sin > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Asin > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Sinh > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Asinh > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Tan > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Atan > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Tanh > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Atanh > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyLowerMatrix, Erf > +{ + using Type = StrictlyLowerMatrix< ForEachTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MATHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MathTrait< StrictlyLowerMatrix, StrictlyLowerMatrix > +{ + using HighType = StrictlyLowerMatrix< typename MathTrait::HighType >; + using LowType = StrictlyLowerMatrix< typename MathTrait::LowType >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct SubmatrixTrait< StrictlyLowerMatrix > +{ + using Type = SubmatrixTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RowTrait< StrictlyLowerMatrix > +{ + using Type = RowTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct ColumnTrait< StrictlyLowerMatrix > +{ + using Type = ColumnTrait_; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// STRICTLYUPPERMATRIX OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name StrictlyUpperMatrix operators */ +//@{ +template< typename MT, bool SO, bool DF > +inline void reset( StrictlyUpperMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void reset( StrictlyUpperMatrix& m, size_t i ); + +template< typename MT, bool SO, bool DF > +inline void clear( StrictlyUpperMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isDefault( const StrictlyUpperMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isIntact( const StrictlyUpperMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void swap( StrictlyUpperMatrix& a, StrictlyUpperMatrix& 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& 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& 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& 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& 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& 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 > 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& m ) +{ + return isDefault_backend( m, typename IsResizable::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 > 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& 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& a, StrictlyUpperMatrix& 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& lhs, + const DenseVector& 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& lhs, + const DenseVector& 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 // Type of the right-hand side sparse vector +inline bool tryAssign( const StrictlyUpperMatrix& lhs, + const SparseVector& 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& lhs, + const SparseVector& 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& lhs, + const DenseMatrix& 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 // Type of the right-hand side dense matrix +inline bool tryAssign( const StrictlyUpperMatrix& lhs, + const DenseMatrix& 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= row ); + const size_t ibegin( ( containsDiagonal )?( column + j - row ):( 0UL ) ); + + for( size_t i=ibegin; i // Type of the right-hand side sparse matrix +inline bool tryAssign( const StrictlyUpperMatrix& lhs, + const SparseMatrix& 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; ivalue() ) ) + 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& lhs, + const SparseMatrix& 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= 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& lhs, + const Vector& 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& lhs, + const Matrix& 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& lhs, + const Vector& 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& lhs, + const Matrix& 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& m ) +{ + return m.matrix_; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Rows< StrictlyUpperMatrix > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Columns< StrictlyUpperMatrix > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSQUARE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsSquare< StrictlyUpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsStrictlyUpper< StrictlyUpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAdaptor< StrictlyUpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESTRICTED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsRestricted< StrictlyUpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct HasConstDataAccess< StrictlyUpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAligned< StrictlyUpperMatrix > : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsPadded< StrictlyUpperMatrix > : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsResizable< StrictlyUpperMatrix > : public BoolConstant< IsResizable::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// REMOVEADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RemoveAdaptor< StrictlyUpperMatrix > +{ + using Type = MT; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DERESTRICTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct DerestrictTrait< StrictlyUpperMatrix > +{ + 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, StaticMatrix > +{ + using Type = AddTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< StaticMatrix, StrictlyUpperMatrix > +{ + using Type = AddTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct AddTrait< StrictlyUpperMatrix, HybridMatrix > +{ + using Type = AddTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< HybridMatrix, StrictlyUpperMatrix > +{ + using Type = AddTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< StrictlyUpperMatrix, DynamicMatrix > +{ + using Type = AddTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< DynamicMatrix, StrictlyUpperMatrix > +{ + using Type = AddTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct AddTrait< StrictlyUpperMatrix, CustomMatrix > +{ + using Type = AddTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CustomMatrix, StrictlyUpperMatrix > +{ + using Type = AddTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< StrictlyUpperMatrix, CompressedMatrix > +{ + using Type = AddTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CompressedMatrix, StrictlyUpperMatrix > +{ + using Type = AddTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct AddTrait< StrictlyUpperMatrix, SymmetricMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct AddTrait< SymmetricMatrix, StrictlyUpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyUpperMatrix, HermitianMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< HermitianMatrix, StrictlyUpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyUpperMatrix, LowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< LowerMatrix, StrictlyUpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyUpperMatrix, UniLowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniLowerMatrix, StrictlyUpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyUpperMatrix, StrictlyLowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyLowerMatrix, StrictlyUpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyUpperMatrix, UpperMatrix > +{ + using Type = UpperMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UpperMatrix, StrictlyUpperMatrix > +{ + using Type = UpperMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyUpperMatrix, UniUpperMatrix > +{ + using Type = UniUpperMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniUpperMatrix, StrictlyUpperMatrix > +{ + using Type = UniUpperMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyUpperMatrix, StrictlyUpperMatrix > +{ + using Type = StrictlyUpperMatrix< AddTrait_ >; +}; +/*! \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, StaticMatrix > +{ + using Type = SubTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< StaticMatrix, StrictlyUpperMatrix > +{ + using Type = SubTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct SubTrait< StrictlyUpperMatrix, HybridMatrix > +{ + using Type = SubTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< HybridMatrix, StrictlyUpperMatrix > +{ + using Type = SubTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< StrictlyUpperMatrix, DynamicMatrix > +{ + using Type = SubTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< DynamicMatrix, StrictlyUpperMatrix > +{ + using Type = SubTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct SubTrait< StrictlyUpperMatrix, CustomMatrix > +{ + using Type = SubTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CustomMatrix, StrictlyUpperMatrix > +{ + using Type = SubTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< StrictlyUpperMatrix, CompressedMatrix > +{ + using Type = SubTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CompressedMatrix, StrictlyUpperMatrix > +{ + using Type = SubTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct SubTrait< StrictlyUpperMatrix, SymmetricMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct SubTrait< SymmetricMatrix, StrictlyUpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyUpperMatrix, HermitianMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< HermitianMatrix, StrictlyUpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyUpperMatrix, LowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< LowerMatrix, StrictlyUpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyUpperMatrix, UniLowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniLowerMatrix, StrictlyUpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyUpperMatrix, StrictlyLowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyLowerMatrix, StrictlyUpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyUpperMatrix, UpperMatrix > +{ + using Type = UpperMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UpperMatrix, StrictlyUpperMatrix > +{ + using Type = UpperMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyUpperMatrix, UniUpperMatrix > +{ + using Type = UpperMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniUpperMatrix, StrictlyUpperMatrix > +{ + using Type = UniUpperMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyUpperMatrix, StrictlyUpperMatrix > +{ + using Type = StrictlyUpperMatrix< SubTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< StrictlyUpperMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = StrictlyUpperMatrix< MultTrait_ >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< T, StrictlyUpperMatrix, EnableIf_< IsNumeric > > +{ + using Type = StrictlyUpperMatrix< MultTrait_ >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< StrictlyUpperMatrix, StaticVector > +{ + using Type = MultTrait_< MT, StaticVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< StaticVector, StrictlyUpperMatrix > +{ + using Type = MultTrait_< StaticVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< StrictlyUpperMatrix, HybridVector > +{ + using Type = MultTrait_< MT, HybridVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< HybridVector, StrictlyUpperMatrix > +{ + using Type = MultTrait_< HybridVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< StrictlyUpperMatrix, DynamicVector > +{ + using Type = MultTrait_< MT, DynamicVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< DynamicVector, StrictlyUpperMatrix > +{ + using Type = MultTrait_< DynamicVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF > +struct MultTrait< StrictlyUpperMatrix, CustomVector > +{ + using Type = MultTrait_< MT, CustomVector >; +}; + +template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF > +struct MultTrait< CustomVector, StrictlyUpperMatrix > +{ + using Type = MultTrait_< CustomVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< StrictlyUpperMatrix, CompressedVector > +{ + using Type = MultTrait_< MT, CompressedVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< CompressedVector, StrictlyUpperMatrix > +{ + using Type = MultTrait_< CompressedVector, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< StrictlyUpperMatrix, StaticMatrix > +{ + using Type = MultTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< StaticMatrix, StrictlyUpperMatrix > +{ + using Type = MultTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< StrictlyUpperMatrix, HybridMatrix > +{ + using Type = MultTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< HybridMatrix, StrictlyUpperMatrix > +{ + using Type = MultTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< StrictlyUpperMatrix, DynamicMatrix > +{ + using Type = MultTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< DynamicMatrix, StrictlyUpperMatrix > +{ + using Type = MultTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct MultTrait< StrictlyUpperMatrix, CustomMatrix > +{ + using Type = MultTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CustomMatrix, StrictlyUpperMatrix > +{ + using Type = MultTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< StrictlyUpperMatrix, CompressedMatrix > +{ + using Type = MultTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CompressedMatrix, StrictlyUpperMatrix > +{ + using Type = MultTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct MultTrait< StrictlyUpperMatrix, SymmetricMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct MultTrait< SymmetricMatrix, StrictlyUpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyUpperMatrix, HermitianMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< HermitianMatrix, StrictlyUpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyUpperMatrix, LowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< LowerMatrix, StrictlyUpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyUpperMatrix, UniLowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniLowerMatrix, StrictlyUpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyUpperMatrix, StrictlyLowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyLowerMatrix, StrictlyUpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyUpperMatrix, UpperMatrix > +{ + using Type = StrictlyUpperMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UpperMatrix, StrictlyUpperMatrix > +{ + using Type = StrictlyUpperMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyUpperMatrix, UniUpperMatrix > +{ + using Type = StrictlyUpperMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniUpperMatrix, StrictlyUpperMatrix > +{ + using Type = StrictlyUpperMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyUpperMatrix, StrictlyUpperMatrix > +{ + using Type = StrictlyUpperMatrix< MultTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct DivTrait< StrictlyUpperMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = StrictlyUpperMatrix< DivTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// FOREACHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Abs > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Floor > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Ceil > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Conj > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Real > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Imag > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Sin > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Asin > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Sinh > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Asinh > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Tan > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Atan > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Tanh > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Atanh > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< StrictlyUpperMatrix, Erf > +{ + using Type = StrictlyUpperMatrix< ForEachTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MATHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MathTrait< StrictlyUpperMatrix, StrictlyUpperMatrix > +{ + using HighType = StrictlyUpperMatrix< typename MathTrait::HighType >; + using LowType = StrictlyUpperMatrix< typename MathTrait::LowType >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct SubmatrixTrait< StrictlyUpperMatrix > +{ + using Type = SubmatrixTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RowTrait< StrictlyUpperMatrix > +{ + using Type = RowTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct ColumnTrait< StrictlyUpperMatrix > +{ + using Type = ColumnTrait_; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// SYMMETRICMATRIX OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name SymmetricMatrix operators */ +//@{ +template< typename MT, bool SO, bool DF, bool NF > +inline void reset( SymmetricMatrix& m ); + +template< typename MT, bool SO, bool DF, bool NF > +inline void reset( SymmetricMatrix& m, size_t i ); + +template< typename MT, bool SO, bool DF, bool NF > +inline void clear( SymmetricMatrix& m ); + +template< typename MT, bool SO, bool DF, bool NF > +inline bool isDefault( const SymmetricMatrix& m ); + +template< typename MT, bool SO, bool DF, bool NF > +inline bool isIntact( const SymmetricMatrix& m ); + +template< typename MT, bool SO, bool DF, bool NF > +inline void swap( SymmetricMatrix& a, SymmetricMatrix& 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& 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& 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& 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 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& 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 > 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& 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& a, SymmetricMatrix& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 2UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 2UL, "Invalid number of columns detected" ); + + typedef ElementType_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 3UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 3UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 4UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 4UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 5UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 5UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 6UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 6UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix 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 or \c complex 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& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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& lhs, + const Matrix& 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& lhs, + const Matrix& 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& lhs, + const Matrix& 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 > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF > +struct Columns< SymmetricMatrix > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSQUARE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF > +struct IsSquare< SymmetricMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF > +struct IsSymmetric< SymmetricMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF > +struct IsHermitian< SymmetricMatrix > + : public BoolConstant< IsBuiltin< ElementType_ >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF > +struct IsAdaptor< SymmetricMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESTRICTED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF > +struct IsRestricted< SymmetricMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool NF > +struct HasConstDataAccess< SymmetricMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF > +struct IsAligned< SymmetricMatrix > : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF > +struct IsPadded< SymmetricMatrix > : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF > +struct IsResizable< SymmetricMatrix > : public BoolConstant< IsResizable::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// REMOVEADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF > +struct RemoveAdaptor< SymmetricMatrix > +{ + 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, StaticMatrix > +{ + using Type = AddTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct AddTrait< StaticMatrix, SymmetricMatrix > +{ + using Type = AddTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, bool NF, typename T, size_t M, size_t N, bool SO2 > +struct AddTrait< SymmetricMatrix, HybridMatrix > +{ + using Type = AddTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct AddTrait< HybridMatrix, SymmetricMatrix > +{ + using Type = AddTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, bool NF, typename T, bool SO2 > +struct AddTrait< SymmetricMatrix, DynamicMatrix > +{ + using Type = AddTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct AddTrait< DynamicMatrix, SymmetricMatrix > +{ + using Type = AddTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, bool NF, typename T, bool AF, bool PF, bool SO2 > +struct AddTrait< SymmetricMatrix, CustomMatrix > +{ + using Type = AddTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct AddTrait< CustomMatrix, SymmetricMatrix > +{ + using Type = AddTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, bool NF, typename T, bool SO2 > +struct AddTrait< SymmetricMatrix, CompressedMatrix > +{ + using Type = AddTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct AddTrait< CompressedMatrix, SymmetricMatrix > +{ + using Type = AddTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF1, typename MT2, bool SO2, bool DF2, bool NF2 > +struct AddTrait< SymmetricMatrix, SymmetricMatrix > +{ + using Type = SymmetricMatrix< AddTrait_ >; +}; +/*! \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, StaticMatrix > +{ + using Type = SubTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct SubTrait< StaticMatrix, SymmetricMatrix > +{ + using Type = SubTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, bool NF, typename T, size_t M, size_t N, bool SO2 > +struct SubTrait< SymmetricMatrix, HybridMatrix > +{ + using Type = SubTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct SubTrait< HybridMatrix, SymmetricMatrix > +{ + using Type = SubTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, bool NF, typename T, bool SO2 > +struct SubTrait< SymmetricMatrix, DynamicMatrix > +{ + using Type = SubTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct SubTrait< DynamicMatrix, SymmetricMatrix > +{ + using Type = SubTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, bool NF, typename T, bool AF, bool PF, bool SO2 > +struct SubTrait< SymmetricMatrix, CustomMatrix > +{ + using Type = SubTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct SubTrait< CustomMatrix, SymmetricMatrix > +{ + using Type = SubTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, bool NF, typename T, bool SO2 > +struct SubTrait< SymmetricMatrix, CompressedMatrix > +{ + using Type = SubTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct SubTrait< CompressedMatrix, SymmetricMatrix > +{ + using Type = SubTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF1, typename MT2, bool SO2, bool DF2, bool NF2 > +struct SubTrait< SymmetricMatrix, SymmetricMatrix > +{ + using Type = SymmetricMatrix< SubTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF, typename T > +struct MultTrait< SymmetricMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = SymmetricMatrix< MultTrait_ >; +}; + +template< typename T, typename MT, bool SO, bool DF, bool NF > +struct MultTrait< T, SymmetricMatrix, EnableIf_< IsNumeric > > +{ + using Type = SymmetricMatrix< MultTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF, typename T, size_t N > +struct MultTrait< SymmetricMatrix, StaticVector > +{ + using Type = MultTrait_< MT, StaticVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF, bool NF > +struct MultTrait< StaticVector, SymmetricMatrix > +{ + using Type = MultTrait_< StaticVector, MT >; +}; + +template< typename MT, bool SO, bool DF, bool NF, typename T, size_t N > +struct MultTrait< SymmetricMatrix, HybridVector > +{ + using Type = MultTrait_< MT, HybridVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF, bool NF > +struct MultTrait< HybridVector, SymmetricMatrix > +{ + using Type = MultTrait_< HybridVector, MT >; +}; + +template< typename MT, bool SO, bool DF, bool NF, typename T > +struct MultTrait< SymmetricMatrix, DynamicVector > +{ + using Type = MultTrait_< MT, DynamicVector >; +}; + +template< typename T, typename MT, bool SO, bool DF, bool NF > +struct MultTrait< DynamicVector, SymmetricMatrix > +{ + using Type = MultTrait_< DynamicVector, MT >; +}; + +template< typename MT, bool SO, bool DF, bool NF, typename T, bool AF, bool PF > +struct MultTrait< SymmetricMatrix, CustomVector > +{ + using Type = MultTrait_< MT, CustomVector >; +}; + +template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF, bool NF > +struct MultTrait< CustomVector, SymmetricMatrix > +{ + using Type = MultTrait_< CustomVector, MT >; +}; + +template< typename MT, bool SO, bool DF, bool NF, typename T > +struct MultTrait< SymmetricMatrix, CompressedVector > +{ + using Type = MultTrait_< MT, CompressedVector >; +}; + +template< typename T, typename MT, bool SO, bool DF, bool NF > +struct MultTrait< CompressedVector, SymmetricMatrix > +{ + using Type = MultTrait_< CompressedVector, MT >; +}; + +template< typename MT, bool SO1, bool DF, bool NF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< SymmetricMatrix, StaticMatrix > +{ + using Type = MultTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct MultTrait< StaticMatrix, SymmetricMatrix > +{ + using Type = MultTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, bool NF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< SymmetricMatrix, HybridMatrix > +{ + using Type = MultTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct MultTrait< HybridMatrix, SymmetricMatrix > +{ + using Type = MultTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, bool NF, typename T, bool SO2 > +struct MultTrait< SymmetricMatrix, DynamicMatrix > +{ + using Type = MultTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct MultTrait< DynamicMatrix, SymmetricMatrix > +{ + using Type = MultTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, bool NF, typename T, bool AF, bool PF, bool SO2 > +struct MultTrait< SymmetricMatrix, CustomMatrix > +{ + using Type = MultTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct MultTrait< CustomMatrix, SymmetricMatrix > +{ + using Type = MultTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, bool NF, typename T, bool SO2 > +struct MultTrait< SymmetricMatrix, CompressedMatrix > +{ + using Type = MultTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF, bool NF > +struct MultTrait< CompressedMatrix, SymmetricMatrix > +{ + using Type = MultTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF1, typename MT2, bool SO2, bool DF2, bool NF2 > +struct MultTrait< SymmetricMatrix, SymmetricMatrix > +{ + using Type = MultTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF, typename T > +struct DivTrait< SymmetricMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = SymmetricMatrix< DivTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// FOREACHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Abs > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Floor > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Ceil > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Conj > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Real > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Imag > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Sqrt > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Cbrt > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, InvCbrt > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF, typename ET > +struct ForEachTrait< SymmetricMatrix, Pow > +{ + using Type = SymmetricMatrix< ForEachTrait_< MT, Pow > >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Exp > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Log > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Log10 > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Sin > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Asin > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Sinh > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Asinh > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Cos > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Acos > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Cosh > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Acosh > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Tan > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Atan > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Tanh > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Atanh > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Erf > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF, bool NF > +struct ForEachTrait< SymmetricMatrix, Erfc > +{ + using Type = SymmetricMatrix< ForEachTrait_ >; +}; +/*! \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, SymmetricMatrix > +{ + typedef SymmetricMatrix< typename MathTrait::HighType > HighType; + typedef SymmetricMatrix< typename MathTrait::LowType > LowType; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF > +struct SubmatrixTrait< SymmetricMatrix > +{ + using Type = SubmatrixTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF > +struct RowTrait< SymmetricMatrix > +{ + using Type = RowTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool NF > +struct ColumnTrait< SymmetricMatrix > +{ + using Type = ColumnTrait_; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// UNILOWERMATRIX OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name UniLowerMatrix operators */ +//@{ +template< typename MT, bool SO, bool DF > +inline void reset( UniLowerMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void reset( UniLowerMatrix& m, size_t i ); + +template< typename MT, bool SO, bool DF > +inline void clear( UniLowerMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isDefault( const UniLowerMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isIntact( const UniLowerMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void swap( UniLowerMatrix& a, UniLowerMatrix& 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& 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& 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& 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& 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& 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 > 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& m ) +{ + return isDefault_backend( m, typename IsResizable::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 > 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& 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& a, UniLowerMatrix& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 2UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 2UL, "Invalid number of columns detected" ); + + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 3UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 3UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 4UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 4UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 5UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 5UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 6UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 6UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + DerestrictTrait_ 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 or \c complex 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& 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 or \c complex 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& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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& A, DenseMatrix& L, + DenseMatrix& U, Matrix& P ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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_ ET3; + typedef ElementType_ ET4; + + const size_t n( (~A).rows() ); + + DerestrictTrait_ U2( derestrict( ~U ) ); + + (~L) = A; + + resize( ~U, n, n ); + reset( U2 ); + + resize( ~P, n, n ); + reset( ~P ); + + for( size_t i=0UL; i // Type of the right-hand side dense vector +inline bool tryAssign( const UniLowerMatrix& lhs, + const DenseVector& 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 // Type of the right-hand side dense vector +inline bool tryAssign( const UniLowerMatrix& lhs, + const DenseVector& 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& lhs, + const SparseVector& 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& lhs, + const SparseVector& 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& lhs, + const DenseMatrix& 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= 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 // Type of the right-hand side dense matrix +inline bool tryAssign( const UniLowerMatrix& lhs, + const DenseMatrix& 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 // Type of the right-hand side sparse matrix +inline bool tryAssign( const UniLowerMatrix& lhs, + const SparseMatrix& 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= 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& lhs, + const SparseMatrix& 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; jindex() != 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& lhs, + const DenseVector& 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 // Type of the right-hand side dense vector +inline bool tryAddAssign( const UniLowerMatrix& lhs, + const DenseVector& 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& lhs, + const SparseVector& 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& lhs, + const SparseVector& 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& lhs, + const DenseMatrix& 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= column ); + const size_t jbegin( ( containsDiagonal )?( row + i - column ):( 0UL ) ); + + for( size_t j=jbegin; j // Type of the right-hand side dense matrix +inline bool tryAddAssign( const UniLowerMatrix& lhs, + const DenseMatrix& 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 // Type of the right-hand side sparse matrix +inline bool tryAddAssign( const UniLowerMatrix& lhs, + const SparseMatrix& 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= 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& lhs, + const SparseMatrix& 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; jvalue() ) ) + 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& lhs, + const Vector& 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& lhs, + const Matrix& 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& lhs, + const Vector& 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& lhs, + const Vector& 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& lhs, + const Vector& 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& m ) +{ + return m.matrix_; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Rows< UniLowerMatrix > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Columns< UniLowerMatrix > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSQUARE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsSquare< UniLowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsUniLower< UniLowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAdaptor< UniLowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESTRICTED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsRestricted< UniLowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct HasConstDataAccess< UniLowerMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAligned< UniLowerMatrix > : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsPadded< UniLowerMatrix > : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsResizable< UniLowerMatrix > : public BoolConstant< IsResizable::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// REMOVEADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RemoveAdaptor< UniLowerMatrix > +{ + using Type = MT; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DERESTRICTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct DerestrictTrait< UniLowerMatrix > +{ + 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, StaticMatrix > +{ + using Type = AddTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< StaticMatrix, UniLowerMatrix > +{ + using Type = AddTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct AddTrait< UniLowerMatrix, HybridMatrix > +{ + using Type = AddTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< HybridMatrix, UniLowerMatrix > +{ + using Type = AddTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< UniLowerMatrix, DynamicMatrix > +{ + using Type = AddTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< DynamicMatrix, UniLowerMatrix > +{ + using Type = AddTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct AddTrait< UniLowerMatrix, CustomMatrix > +{ + using Type = AddTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CustomMatrix, UniLowerMatrix > +{ + using Type = AddTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< UniLowerMatrix, CompressedMatrix > +{ + using Type = AddTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CompressedMatrix, UniLowerMatrix > +{ + using Type = AddTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct AddTrait< UniLowerMatrix, SymmetricMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct AddTrait< SymmetricMatrix, UniLowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniLowerMatrix, HermitianMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< HermitianMatrix, UniLowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniLowerMatrix, LowerMatrix > +{ + using Type = LowerMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< LowerMatrix, UniLowerMatrix > +{ + using Type = LowerMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniLowerMatrix, UniLowerMatrix > +{ + using Type = LowerMatrix< AddTrait_ >; +}; +/*! \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, StaticMatrix > +{ + using Type = SubTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< StaticMatrix, UniLowerMatrix > +{ + using Type = SubTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct SubTrait< UniLowerMatrix, HybridMatrix > +{ + using Type = SubTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< HybridMatrix, UniLowerMatrix > +{ + using Type = SubTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< UniLowerMatrix, DynamicMatrix > +{ + using Type = SubTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< DynamicMatrix, UniLowerMatrix > +{ + using Type = SubTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct SubTrait< UniLowerMatrix, CustomMatrix > +{ + using Type = SubTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CustomMatrix, UniLowerMatrix > +{ + using Type = SubTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< UniLowerMatrix, CompressedMatrix > +{ + using Type = SubTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CompressedMatrix, UniLowerMatrix > +{ + using Type = SubTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct SubTrait< UniLowerMatrix, SymmetricMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct SubTrait< SymmetricMatrix, UniLowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniLowerMatrix, HermitianMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< HermitianMatrix, UniLowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniLowerMatrix, LowerMatrix > +{ + using Type = LowerMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< LowerMatrix, UniLowerMatrix > +{ + using Type = LowerMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniLowerMatrix, UniLowerMatrix > +{ + using Type = LowerMatrix< SubTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< UniLowerMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = LowerMatrix< MultTrait_ >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< T, UniLowerMatrix, EnableIf_< IsNumeric > > +{ + using Type = LowerMatrix< MultTrait_ >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< UniLowerMatrix, StaticVector > +{ + using Type = MultTrait_< MT, StaticVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< StaticVector, UniLowerMatrix > +{ + using Type = MultTrait_< StaticVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< UniLowerMatrix, HybridVector > +{ + using Type = MultTrait_< MT, HybridVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< HybridVector, UniLowerMatrix > +{ + using Type = MultTrait_< HybridVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< UniLowerMatrix, DynamicVector > +{ + using Type = MultTrait_< MT, DynamicVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< DynamicVector, UniLowerMatrix > +{ + using Type = MultTrait_< DynamicVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF > +struct MultTrait< UniLowerMatrix, CustomVector > +{ + using Type = MultTrait_< MT, CustomVector >; +}; + +template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF > +struct MultTrait< CustomVector, UniLowerMatrix > +{ + using Type = MultTrait_< CustomVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< UniLowerMatrix, CompressedVector > +{ + using Type = MultTrait_< MT, CompressedVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< CompressedVector, UniLowerMatrix > +{ + using Type = MultTrait_< CompressedVector, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< UniLowerMatrix, StaticMatrix > +{ + using Type = MultTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< StaticMatrix, UniLowerMatrix > +{ + using Type = MultTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< UniLowerMatrix, HybridMatrix > +{ + using Type = MultTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< HybridMatrix, UniLowerMatrix > +{ + using Type = MultTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< UniLowerMatrix, DynamicMatrix > +{ + using Type = MultTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< DynamicMatrix, UniLowerMatrix > +{ + using Type = MultTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct MultTrait< UniLowerMatrix, CustomMatrix > +{ + using Type = MultTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CustomMatrix, UniLowerMatrix > +{ + using Type = MultTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< UniLowerMatrix, CompressedMatrix > +{ + using Type = MultTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CompressedMatrix, UniLowerMatrix > +{ + using Type = MultTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct MultTrait< UniLowerMatrix, SymmetricMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct MultTrait< SymmetricMatrix, UniLowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniLowerMatrix, HermitianMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< HermitianMatrix, UniLowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniLowerMatrix, LowerMatrix > +{ + using Type = LowerMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< LowerMatrix, UniLowerMatrix > +{ + using Type = LowerMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniLowerMatrix, UniLowerMatrix > +{ + using Type = UniLowerMatrix< MultTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct DivTrait< UniLowerMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = LowerMatrix< DivTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// FOREACHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename ET > +struct ForEachTrait< UniLowerMatrix, Pow > +{ + using Type = UniLowerMatrix< ForEachTrait_< MT, Pow > >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MATHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MathTrait< UniLowerMatrix, UniLowerMatrix > +{ + using HighType = UniLowerMatrix< typename MathTrait::HighType >; + using LowType = UniLowerMatrix< typename MathTrait::LowType >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct SubmatrixTrait< UniLowerMatrix > +{ + using Type = SubmatrixTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RowTrait< UniLowerMatrix > +{ + using Type = RowTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct ColumnTrait< UniLowerMatrix > +{ + using Type = ColumnTrait_; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// UNIUPPERMATRIX OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name UniUpperMatrix operators */ +//@{ +template< typename MT, bool SO, bool DF > +inline void reset( UniUpperMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void reset( UniUpperMatrix& m, size_t i ); + +template< typename MT, bool SO, bool DF > +inline void clear( UniUpperMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isDefault( const UniUpperMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isIntact( const UniUpperMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void swap( UniUpperMatrix& a, UniUpperMatrix& 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& 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& 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& 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& 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& 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 > 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& 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 > 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& m ) +{ + return isDefault_backend( m, typename IsResizable::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& a, UniUpperMatrix& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 2UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 2UL, "Invalid number of columns detected" ); + + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 3UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 3UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 4UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 4UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 5UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 5UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 6UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 6UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + DerestrictTrait_ 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 or \c complex 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& 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 or \c complex 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& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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& A, DenseMatrix& L, + DenseMatrix& U, Matrix& P ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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_ ET2; + typedef ElementType_ ET4; + + const size_t n( (~A).rows() ); + + DerestrictTrait_ L2( derestrict( ~L ) ); + + (~U) = A; + + resize( ~L, n, n ); + reset( L2 ); + + resize( ~P, n, n ); + reset( ~P ); + + for( size_t i=0UL; i // Type of the right-hand side dense vector +inline bool tryAssign( const UniUpperMatrix& lhs, + const DenseVector& 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& lhs, + const DenseVector& 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 // Type of the right-hand side sparse vector +inline bool tryAssign( const UniUpperMatrix& lhs, + const SparseVector& 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& lhs, + const SparseVector& 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& lhs, + const DenseMatrix& 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 // Type of the right-hand side dense matrix +inline bool tryAssign( const UniUpperMatrix& lhs, + const DenseMatrix& 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= 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 // Type of the right-hand side sparse matrix +inline bool tryAssign( const UniUpperMatrix& lhs, + const SparseMatrix& 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; iindex() != 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& lhs, + const SparseMatrix& 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= 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& lhs, + const DenseVector& 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& lhs, + const DenseVector& 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 // Type of the right-hand side sparse vector +inline bool tryAddAssign( const UniUpperMatrix& lhs, + const SparseVector& 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& lhs, + const SparseVector& 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& lhs, + const DenseMatrix& 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 // Type of the right-hand side dense matrix +inline bool tryAddAssign( const UniUpperMatrix& lhs, + const DenseMatrix& 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= row ); + const size_t ibegin( ( containsDiagonal )?( column + j - row ):( 0UL ) ); + + for( size_t i=ibegin; i // Type of the right-hand side sparse matrix +inline bool tryAddAssign( const UniUpperMatrix& lhs, + const SparseMatrix& 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; ivalue() ) ) + 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& lhs, + const SparseMatrix& 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= 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& lhs, + const Vector& 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& lhs, + const Matrix& 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& lhs, + const Vector& 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& lhs, + const Vector& 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& lhs, + const Vector& 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& m ) +{ + return m.matrix_; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Rows< UniUpperMatrix > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Columns< UniUpperMatrix > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSQUARE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsSquare< UniUpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsUniUpper< UniUpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAdaptor< UniUpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESTRICTED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsRestricted< UniUpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct HasConstDataAccess< UniUpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAligned< UniUpperMatrix > : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsPadded< UniUpperMatrix > : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsResizable< UniUpperMatrix > : public BoolConstant< IsResizable::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// REMOVEADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RemoveAdaptor< UniUpperMatrix > +{ + using Type = MT; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DERESTRICTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct DerestrictTrait< UniUpperMatrix > +{ + 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, StaticMatrix > +{ + using Type = AddTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< StaticMatrix, UniUpperMatrix > +{ + using Type = AddTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct AddTrait< UniUpperMatrix, HybridMatrix > +{ + using Type = AddTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< HybridMatrix, UniUpperMatrix > +{ + using Type = AddTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< UniUpperMatrix, DynamicMatrix > +{ + using Type = AddTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< DynamicMatrix, UniUpperMatrix > +{ + using Type = AddTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct AddTrait< UniUpperMatrix, CustomMatrix > +{ + using Type = AddTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CustomMatrix, UniUpperMatrix > +{ + using Type = AddTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< UniUpperMatrix, CompressedMatrix > +{ + using Type = AddTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CompressedMatrix, UniUpperMatrix > +{ + using Type = AddTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct AddTrait< UniUpperMatrix, SymmetricMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct AddTrait< SymmetricMatrix, UniUpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniUpperMatrix, HermitianMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< HermitianMatrix, UniUpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniUpperMatrix, LowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< LowerMatrix, UniUpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniUpperMatrix, UniLowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniLowerMatrix, UniUpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniUpperMatrix, StrictlyLowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyLowerMatrix, UniUpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniUpperMatrix, UpperMatrix > +{ + using Type = UpperMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UpperMatrix, UniUpperMatrix > +{ + using Type = UpperMatrix< AddTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniUpperMatrix, UniUpperMatrix > +{ + using Type = UpperMatrix< AddTrait_ >; +}; +/*! \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, StaticMatrix > +{ + using Type = SubTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< StaticMatrix, UniUpperMatrix > +{ + using Type = SubTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct SubTrait< UniUpperMatrix, HybridMatrix > +{ + using Type = SubTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< HybridMatrix, UniUpperMatrix > +{ + using Type = SubTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< UniUpperMatrix, DynamicMatrix > +{ + using Type = SubTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< DynamicMatrix, UniUpperMatrix > +{ + using Type = SubTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct SubTrait< UniUpperMatrix, CustomMatrix > +{ + using Type = SubTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CustomMatrix, UniUpperMatrix > +{ + using Type = SubTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< UniUpperMatrix, CompressedMatrix > +{ + using Type = SubTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CompressedMatrix, UniUpperMatrix > +{ + using Type = SubTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct SubTrait< UniUpperMatrix, SymmetricMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct SubTrait< SymmetricMatrix, UniUpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniUpperMatrix, HermitianMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< HermitianMatrix, UniUpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniUpperMatrix, LowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< LowerMatrix, UniUpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniUpperMatrix, UniLowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniLowerMatrix, UniUpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniUpperMatrix, StrictlyLowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyLowerMatrix, UniUpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniUpperMatrix, UpperMatrix > +{ + using Type = UpperMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UpperMatrix, UniUpperMatrix > +{ + using Type = UpperMatrix< SubTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniUpperMatrix, UniUpperMatrix > +{ + using Type = UpperMatrix< SubTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< UniUpperMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = UpperMatrix< MultTrait_ >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< T, UniUpperMatrix, EnableIf_< IsNumeric > > +{ + using Type = UpperMatrix< MultTrait_ >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< UniUpperMatrix, StaticVector > +{ + using Type = MultTrait_< MT, StaticVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< StaticVector, UniUpperMatrix > +{ + using Type = MultTrait_< StaticVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< UniUpperMatrix, HybridVector > +{ + using Type = MultTrait_< MT, HybridVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< HybridVector, UniUpperMatrix > +{ + using Type = MultTrait_< HybridVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< UniUpperMatrix, DynamicVector > +{ + using Type = MultTrait_< MT, DynamicVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< DynamicVector, UniUpperMatrix > +{ + using Type = MultTrait_< DynamicVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF > +struct MultTrait< UniUpperMatrix, CustomVector > +{ + using Type = MultTrait_< MT, CustomVector >; +}; + +template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF > +struct MultTrait< CustomVector, UniUpperMatrix > +{ + using Type = MultTrait_< CustomVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< UniUpperMatrix, CompressedVector > +{ + using Type = MultTrait_< MT, CompressedVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< CompressedVector, UniUpperMatrix > +{ + using Type = MultTrait_< CompressedVector, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< UniUpperMatrix, StaticMatrix > +{ + using Type = MultTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< StaticMatrix, UniUpperMatrix > +{ + using Type = MultTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< UniUpperMatrix, HybridMatrix > +{ + using Type = MultTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< HybridMatrix, UniUpperMatrix > +{ + using Type = MultTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< UniUpperMatrix, DynamicMatrix > +{ + using Type = MultTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< DynamicMatrix, UniUpperMatrix > +{ + using Type = MultTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct MultTrait< UniUpperMatrix, CustomMatrix > +{ + using Type = MultTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CustomMatrix, UniUpperMatrix > +{ + using Type = MultTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< UniUpperMatrix, CompressedMatrix > +{ + using Type = MultTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CompressedMatrix, UniUpperMatrix > +{ + using Type = MultTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct MultTrait< UniUpperMatrix, SymmetricMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct MultTrait< SymmetricMatrix, UniUpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniUpperMatrix, HermitianMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< HermitianMatrix, UniUpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniUpperMatrix, LowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< LowerMatrix, UniUpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniUpperMatrix, UniLowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniLowerMatrix, UniUpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniUpperMatrix, StrictlyLowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyLowerMatrix, UniUpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniUpperMatrix, UpperMatrix > +{ + using Type = UpperMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UpperMatrix, UniUpperMatrix > +{ + using Type = UpperMatrix< MultTrait_ >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniUpperMatrix, UniUpperMatrix > +{ + using Type = UniUpperMatrix< MultTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct DivTrait< UniUpperMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = UpperMatrix< DivTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// FOREACHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename ET > +struct ForEachTrait< UniUpperMatrix, Pow > +{ + using Type = UniUpperMatrix< ForEachTrait_< MT, Pow > >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MATHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MathTrait< UniUpperMatrix, UniUpperMatrix > +{ + using HighType = UniUpperMatrix< typename MathTrait::HighType >; + using LowType = UniUpperMatrix< typename MathTrait::LowType >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct SubmatrixTrait< UniUpperMatrix > +{ + using Type = SubmatrixTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RowTrait< UniUpperMatrix > +{ + using Type = RowTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct ColumnTrait< UniUpperMatrix > +{ + using Type = ColumnTrait_; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// UPPERMATRIX OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name UpperMatrix operators */ +//@{ +template< typename MT, bool SO, bool DF > +inline void reset( UpperMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void reset( UpperMatrix& m, size_t i ); + +template< typename MT, bool SO, bool DF > +inline void clear( UpperMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isDefault( const UpperMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline bool isIntact( const UpperMatrix& m ); + +template< typename MT, bool SO, bool DF > +inline void swap( UpperMatrix& a, UpperMatrix& 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& 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& 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& 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 > 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& 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 > 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& 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& a, UpperMatrix& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 2UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 2UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 3UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 3UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 4UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 4UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 5UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 5UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( m.rows() == 6UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( m.columns() == 6UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix A( m ); + DerestrictTrait_ 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 or \c complex 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& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + DerestrictTrait_ 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 or \c complex 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& 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 or \c complex 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& 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 or \c complex 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& m ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( isDiagonal( ~m ), "Violation of preconditions detected" ); + + DerestrictTrait_ A( derestrict( ~m ) ); + + for( size_t i=0UL; i +inline void lu( const UpperMatrix& A, DenseMatrix& L, + DenseMatrix& U, Matrix& P ) +{ + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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_ ET2; + typedef ElementType_ ET4; + + const size_t n( (~A).rows() ); + + DerestrictTrait_ L2( derestrict( ~L ) ); + + (~U) = A; + + resize( ~L, n, n ); + reset( L2 ); + + resize( ~P, n, n ); + reset( ~P ); + + for( size_t i=0UL; i // Type of the right-hand side dense vector +inline bool tryAssign( const UpperMatrix& lhs, + const DenseVector& 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& lhs, + const DenseVector& 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 // Type of the right-hand side sparse vector +inline bool tryAssign( const UpperMatrix& lhs, + const SparseVector& 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& lhs, + const SparseVector& 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& lhs, + const DenseMatrix& 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 // Type of the right-hand side dense matrix +inline bool tryAssign( const UpperMatrix& lhs, + const DenseMatrix& 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= row ); + const size_t ibegin( ( containsDiagonal )?( column + j - row + 1UL ):( 0UL ) ); + + for( size_t i=ibegin; i // Type of the right-hand side sparse matrix +inline bool tryAssign( const UpperMatrix& lhs, + const SparseMatrix& 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; ivalue() ) ) + 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& lhs, + const SparseMatrix& 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= 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& lhs, + const Vector& 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& lhs, + const Matrix& 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& lhs, + const Vector& 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& lhs, + const Matrix& 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& m ) +{ + return m.matrix_; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Rows< UpperMatrix > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct Columns< UpperMatrix > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSQUARE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsSquare< UpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsUpper< UpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAdaptor< UpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESTRICTED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsRestricted< UpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct HasConstDataAccess< UpperMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsAligned< UpperMatrix > : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsPadded< UpperMatrix > : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct IsResizable< UpperMatrix > : public BoolConstant< IsResizable::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// REMOVEADAPTOR SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RemoveAdaptor< UpperMatrix > +{ + using Type = MT; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DERESTRICTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct DerestrictTrait< UpperMatrix > +{ + 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, StaticMatrix > +{ + using Type = AddTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< StaticMatrix, UpperMatrix > +{ + using Type = AddTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct AddTrait< UpperMatrix, HybridMatrix > +{ + using Type = AddTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< HybridMatrix, UpperMatrix > +{ + using Type = AddTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< UpperMatrix, DynamicMatrix > +{ + using Type = AddTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< DynamicMatrix, UpperMatrix > +{ + using Type = AddTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct AddTrait< UpperMatrix, CustomMatrix > +{ + using Type = AddTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CustomMatrix, UpperMatrix > +{ + using Type = AddTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct AddTrait< UpperMatrix, CompressedMatrix > +{ + using Type = AddTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct AddTrait< CompressedMatrix, UpperMatrix > +{ + using Type = AddTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct AddTrait< UpperMatrix, SymmetricMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct AddTrait< SymmetricMatrix, UpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UpperMatrix, HermitianMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< HermitianMatrix, UpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UpperMatrix, LowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< LowerMatrix, UpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UpperMatrix, UniLowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UniLowerMatrix, UpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UpperMatrix, StrictlyLowerMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< StrictlyLowerMatrix, UpperMatrix > +{ + using Type = AddTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct AddTrait< UpperMatrix, UpperMatrix > +{ + using Type = UpperMatrix< AddTrait_ >; +}; +/*! \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, StaticMatrix > +{ + using Type = SubTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< StaticMatrix, UpperMatrix > +{ + using Type = SubTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct SubTrait< UpperMatrix, HybridMatrix > +{ + using Type = SubTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< HybridMatrix, UpperMatrix > +{ + using Type = SubTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< UpperMatrix, DynamicMatrix > +{ + using Type = SubTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< DynamicMatrix, UpperMatrix > +{ + using Type = SubTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct SubTrait< UpperMatrix, CustomMatrix > +{ + using Type = SubTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CustomMatrix, UpperMatrix > +{ + using Type = SubTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct SubTrait< UpperMatrix, CompressedMatrix > +{ + using Type = SubTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct SubTrait< CompressedMatrix, UpperMatrix > +{ + using Type = SubTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct SubTrait< UpperMatrix, SymmetricMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct SubTrait< SymmetricMatrix, UpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UpperMatrix, HermitianMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< HermitianMatrix, UpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UpperMatrix, LowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< LowerMatrix, UpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UpperMatrix, UniLowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UniLowerMatrix, UpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UpperMatrix, StrictlyLowerMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< StrictlyLowerMatrix, UpperMatrix > +{ + using Type = SubTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct SubTrait< UpperMatrix, UpperMatrix > +{ + using Type = UpperMatrix< SubTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< UpperMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = UpperMatrix< MultTrait_ >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< T, UpperMatrix, EnableIf_< IsNumeric > > +{ + using Type = UpperMatrix< MultTrait_ >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< UpperMatrix, StaticVector > +{ + using Type = MultTrait_< MT, StaticVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< StaticVector, UpperMatrix > +{ + using Type = MultTrait_< StaticVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, size_t N > +struct MultTrait< UpperMatrix, HybridVector > +{ + using Type = MultTrait_< MT, HybridVector >; +}; + +template< typename T, size_t N, typename MT, bool SO, bool DF > +struct MultTrait< HybridVector, UpperMatrix > +{ + using Type = MultTrait_< HybridVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< UpperMatrix, DynamicVector > +{ + using Type = MultTrait_< MT, DynamicVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< DynamicVector, UpperMatrix > +{ + using Type = MultTrait_< DynamicVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T, bool AF, bool PF > +struct MultTrait< UpperMatrix, CustomVector > +{ + using Type = MultTrait_< MT, CustomVector >; +}; + +template< typename T, bool AF, bool PF, typename MT, bool SO, bool DF > +struct MultTrait< CustomVector, UpperMatrix > +{ + using Type = MultTrait_< CustomVector, MT >; +}; + +template< typename MT, bool SO, bool DF, typename T > +struct MultTrait< UpperMatrix, CompressedVector > +{ + using Type = MultTrait_< MT, CompressedVector >; +}; + +template< typename T, typename MT, bool SO, bool DF > +struct MultTrait< CompressedVector, UpperMatrix > +{ + using Type = MultTrait_< CompressedVector, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< UpperMatrix, StaticMatrix > +{ + using Type = MultTrait_< MT, StaticMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< StaticMatrix, UpperMatrix > +{ + using Type = MultTrait_< StaticMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, size_t M, size_t N, bool SO2 > +struct MultTrait< UpperMatrix, HybridMatrix > +{ + using Type = MultTrait_< MT, HybridMatrix >; +}; + +template< typename T, size_t M, size_t N, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< HybridMatrix, UpperMatrix > +{ + using Type = MultTrait_< HybridMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< UpperMatrix, DynamicMatrix > +{ + using Type = MultTrait_< MT, DynamicMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< DynamicMatrix, UpperMatrix > +{ + using Type = MultTrait_< DynamicMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool AF, bool PF, bool SO2 > +struct MultTrait< UpperMatrix, CustomMatrix > +{ + using Type = MultTrait_< MT, CustomMatrix >; +}; + +template< typename T, bool AF, bool PF, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CustomMatrix, UpperMatrix > +{ + using Type = MultTrait_< CustomMatrix, MT >; +}; + +template< typename MT, bool SO1, bool DF, typename T, bool SO2 > +struct MultTrait< UpperMatrix, CompressedMatrix > +{ + using Type = MultTrait_< MT, CompressedMatrix >; +}; + +template< typename T, bool SO1, typename MT, bool SO2, bool DF > +struct MultTrait< CompressedMatrix, UpperMatrix > +{ + using Type = MultTrait_< CompressedMatrix, MT >; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2, bool NF > +struct MultTrait< UpperMatrix, SymmetricMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, bool NF, typename MT2, bool SO2, bool DF2 > +struct MultTrait< SymmetricMatrix, UpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UpperMatrix, HermitianMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< HermitianMatrix, UpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UpperMatrix, LowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< LowerMatrix, UpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UpperMatrix, UniLowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UniLowerMatrix, UpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UpperMatrix, StrictlyLowerMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< StrictlyLowerMatrix, UpperMatrix > +{ + using Type = MultTrait_; +}; + +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MultTrait< UpperMatrix, UpperMatrix > +{ + using Type = UpperMatrix< MultTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, typename T > +struct DivTrait< UpperMatrix, T, EnableIf_< IsNumeric > > +{ + using Type = UpperMatrix< DivTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// FOREACHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Abs > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Floor > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Ceil > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Conj > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Real > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Imag > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Sin > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Asin > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Sinh > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Asinh > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Tan > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Atan > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Tanh > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Atanh > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; + +template< typename MT, bool SO, bool DF > +struct ForEachTrait< UpperMatrix, Erf > +{ + using Type = UpperMatrix< ForEachTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MATHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, bool SO1, bool DF1, typename MT2, bool SO2, bool DF2 > +struct MathTrait< UpperMatrix, UpperMatrix > +{ + using HighType = UpperMatrix< typename MathTrait::HighType >; + using LowType = UpperMatrix< typename MathTrait::LowType >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct SubmatrixTrait< UpperMatrix > +{ + using Type = SubmatrixTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct RowTrait< UpperMatrix > +{ + using Type = RowTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF > +struct ColumnTrait< UpperMatrix > +{ + using Type = ColumnTrait_; +}; +/*! \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 +#include + + +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 > A; + + // Definition of a resizable column-major dense diagonal matrix based on HybridMatrix + blaze::DiagonalMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense diagonal matrix based on DynamicMatrix + blaze::DiagonalMatrix< blaze::DynamicMatrix > C; + + // Definition of a fixed-size row-major dense diagonal matrix based on CustomMatrix + blaze::DiagonalMatrix< blaze::CustomMatrix > D; + + // Definition of a compressed row-major single precision diagonal matrix + blaze::DiagonalMatrix< blaze::CompressedMatrix > 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: +// +// -# \ref diagonalmatrix_square +// -# \ref diagonalmatrix_diagonal +// -# \ref diagonalmatrix_initialization +// -# \ref diagonalmatrix_storage +// +// \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 > 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 > A; + + // Compilation error: the provided matrix type is not a square matrix type + DiagonalMatrix< StaticMatrix > 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 > 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 B( 3.0, 0.0, 0.0, + 0.0, -2.0, 0.0, + 0.0, 0.0, 4.0 ); + + DiagonalMatrix< DynamicMatrix > C( B ); // OK + + // Assignment of a non-diagonal dense matrix + StaticMatrix 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 > 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 > 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 > A1( 4 ), A2( 4 ); + + // Setup of a 4-dimensional vector + // + // v = ( 0 0 3 0 ) + // + DynamicVector 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 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 A( 5, 5 ); + + // 5x5 row-major diagonal dynamic matrix with default initialized lower and upper matrix + DiagonalMatrix< DynamicMatrix > 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 > SmallDiagonalMatrix; + + // Recommendation 2: use sparse matrices for large diagonal matrices + typedef blaze::DiagonalMatrix< blaze::CompressedMatrix > 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 A( 3, 3 ); + CompressedMatrix B( 3, 3 ); + + DiagonalMatrix< DynamicMatrix > C( 3 ); + DiagonalMatrix< CompressedMatrix > D( 3 ); + + DiagonalMatrix< HybridMatrix > E; + DiagonalMatrix< StaticMatrix > 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 > > 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 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 > A; + DynamicMatrix 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 > A; + DynamicVector 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 > A, C; + DynamicMatrix 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 > 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::value // Storage order of the adapted matrix + , bool DF = IsDenseMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public DenseMatrix< DiagonalMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the dense matrix. + typedef TransposeType_ TT; //!< Transpose type of the dense matrix. + typedef ElementType_ ET; //!< Element type of the dense matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DiagonalMatrix This; //!< Type of this DiagonalMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this DiagonalMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef DiagonalMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef DiagonalMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef SIMDType_ SIMDType; //!< SIMD type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef DiagonalProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant matrix value. + typedef ConstPointer_ ConstPointer; //!< Pointer to a constant matrix value. + typedef ConstIterator_ 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::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_ ValueType; //!< Type of the underlying elements. + typedef DiagonalProxy PointerType; //!< Pointer return type. + typedef DiagonalProxy 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 > 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 > 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, DiagonalMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, DiagonalMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, DiagonalMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, DiagonalMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, DiagonalMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, DiagonalMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DiagonalMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, DiagonalMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& 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& m ); + + template< typename MT2, bool SO2, bool DF2 > + friend MT2& derestrict( DiagonalMatrix& 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::value == Columns::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::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::DiagonalMatrix( const A1& a1 ) + : matrix_( construct( a1, typename IsResizable::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::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 > 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::DiagonalMatrix( initializer_list< initializer_list > 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 > 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::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 > 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::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::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::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::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::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::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::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::Reference + DiagonalMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename DiagonalMatrix::ConstReference + DiagonalMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename DiagonalMatrix::Reference + DiagonalMatrix::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::ConstReference + DiagonalMatrix::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::ConstPointer + DiagonalMatrix::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::ConstPointer + DiagonalMatrix::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::Iterator + DiagonalMatrix::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::ConstIterator + DiagonalMatrix::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::ConstIterator + DiagonalMatrix::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::Iterator + DiagonalMatrix::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::ConstIterator + DiagonalMatrix::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::ConstIterator + DiagonalMatrix::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& + DiagonalMatrix::operator=( const ElementType& rhs ) +{ + if( SO ) { + for( size_t j=0UL; j > 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& + DiagonalMatrix::operator=( initializer_list< initializer_list > 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 > 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& + DiagonalMatrix::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& + DiagonalMatrix::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& + DiagonalMatrix::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, DiagonalMatrix& > + DiagonalMatrix::operator=( const Matrix& rhs ) +{ + if( !IsDiagonal::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, DiagonalMatrix& > + DiagonalMatrix::operator=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" ); + } + + if( IsDiagonal::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, DiagonalMatrix& > + DiagonalMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsDiagonal::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, DiagonalMatrix& > + DiagonalMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" ); + } + + if( IsDiagonal::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ 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, DiagonalMatrix& > + DiagonalMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsDiagonal::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, DiagonalMatrix& > + DiagonalMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" ); + } + + if( IsDiagonal::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ 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& + DiagonalMatrix::operator*=( const Matrix& 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, DiagonalMatrix >& + DiagonalMatrix::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, DiagonalMatrix >& + DiagonalMatrix::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::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::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::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::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::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::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::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::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::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::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::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::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::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& DiagonalMatrix::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::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::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::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::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::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::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::SIMDType + DiagonalMatrix::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::SIMDType + DiagonalMatrix::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::SIMDType + DiagonalMatrix::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::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::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 // 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::construct( const Matrix& m, T ) +{ + const MT tmp( ~m ); + + if( !IsDiagonal::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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, ElementType_ > +{ + private: + //**Type definitions**************************************************************************** + //! Reference type of the underlying matrix type. + typedef AddConst_< typename MT::Reference > ReferenceType; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef ElementType_ RepresentedType; //!< Type of the represented matrix element. + typedef AddReference_ 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 list ); + + template< typename T > + inline DiagonalProxy& operator=( initializer_list< initializer_list > 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::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::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& DiagonalProxy::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& DiagonalProxy::operator=( initializer_list 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& DiagonalProxy::operator=( initializer_list< initializer_list > 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& DiagonalProxy::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& DiagonalProxy::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& DiagonalProxy::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& DiagonalProxy::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& DiagonalProxy::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::RawReference DiagonalProxy::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::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::operator ConstReference() const noexcept +{ + return static_cast( value_ ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name DiagonalProxy global functions */ +//@{ +template< typename MT > +inline void reset( const DiagonalProxy& proxy ); + +template< typename MT > +inline void clear( const DiagonalProxy& proxy ); + +template< typename MT > +inline bool isDefault( const DiagonalProxy& proxy ); + +template< typename MT > +inline bool isReal( const DiagonalProxy& proxy ); + +template< typename MT > +inline bool isZero( const DiagonalProxy& proxy ); + +template< typename MT > +inline bool isOne( const DiagonalProxy& proxy ); + +template< typename MT > +inline bool isnan( const DiagonalProxy& 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& 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& 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& 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& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public SparseMatrix< DiagonalMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the sparse matrix. + typedef TransposeType_ TT; //!< Transpose type of the sparse matrix. + typedef ElementType_ ET; //!< Element type of the sparse matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DiagonalMatrix This; //!< Type of this DiagonalMatrix instance. + typedef SparseMatrix BaseType; //!< Base type of this DiagonalMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef DiagonalMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef DiagonalMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef DiagonalProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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::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& nonzeros ); + + inline DiagonalMatrix( const DiagonalMatrix& m ); + inline DiagonalMatrix( DiagonalMatrix&& m ) noexcept; + + template< typename MT2, bool SO2 > + inline DiagonalMatrix( const Matrix& 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, DiagonalMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, DiagonalMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, DiagonalMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, DiagonalMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, DiagonalMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, DiagonalMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DiagonalMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, DiagonalMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& m ); + + template< typename MT2, bool SO2, bool DF2 > + friend MT2& derestrict( DiagonalMatrix& 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::value == Columns::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::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::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::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::DiagonalMatrix( size_t n, const std::vector& 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::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::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::DiagonalMatrix( const Matrix& m ) + : matrix_( ~m ) // The adapted sparse matrix +{ + if( !IsDiagonal::value && !isDiagonal( matrix_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of diagonal matrix" ); + } + + if( !IsDiagonal::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::Reference + DiagonalMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename DiagonalMatrix::ConstReference + DiagonalMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename DiagonalMatrix::Reference + DiagonalMatrix::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::ConstReference + DiagonalMatrix::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::Iterator + DiagonalMatrix::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::ConstIterator + DiagonalMatrix::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::ConstIterator + DiagonalMatrix::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::Iterator + DiagonalMatrix::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::ConstIterator + DiagonalMatrix::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::ConstIterator + DiagonalMatrix::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& + DiagonalMatrix::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& + DiagonalMatrix::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, DiagonalMatrix& > + DiagonalMatrix::operator=( const Matrix& rhs ) +{ + if( !IsDiagonal::value && !isDiagonal( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" ); + } + + matrix_ = ~rhs; + + if( !IsDiagonal::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, DiagonalMatrix& > + DiagonalMatrix::operator=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" ); + } + + if( IsDiagonal::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::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, DiagonalMatrix& > + DiagonalMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsDiagonal::value && !isDiagonal( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" ); + } + + matrix_ += ~rhs; + + if( !IsDiagonal::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, DiagonalMatrix& > + DiagonalMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" ); + } + + if( IsDiagonal::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ tmp( ~rhs ); + + if( !isDiagonal( tmp ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" ); + } + + matrix_ += tmp; + } + + if( !IsDiagonal::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, DiagonalMatrix& > + DiagonalMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsDiagonal::value && !isDiagonal( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" ); + } + + matrix_ -= ~rhs; + + if( !IsDiagonal::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, DiagonalMatrix& > + DiagonalMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" ); + } + + if( IsDiagonal::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ tmp( ~rhs ); + + if( !isDiagonal( tmp ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to diagonal matrix" ); + } + + matrix_ -= tmp; + } + + if( !IsDiagonal::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& + DiagonalMatrix::operator*=( const Matrix& 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::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, DiagonalMatrix >& + DiagonalMatrix::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, DiagonalMatrix >& + DiagonalMatrix::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::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::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::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::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::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::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::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::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::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::Iterator + DiagonalMatrix::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::Iterator + DiagonalMatrix::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::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::Iterator + DiagonalMatrix::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::Iterator + DiagonalMatrix::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::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::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::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::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::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& + DiagonalMatrix::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& + DiagonalMatrix::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::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::resetNonDiagonal() +{ + for( size_t i=0UL; i // Storage order of the adapted sparse matrix +inline typename DiagonalMatrix::Iterator + DiagonalMatrix::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::ConstIterator + DiagonalMatrix::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::Iterator + DiagonalMatrix::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::ConstIterator + DiagonalMatrix::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::Iterator + DiagonalMatrix::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::ConstIterator + DiagonalMatrix::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 > 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::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::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::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::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::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::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 +#include +#include + + +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 > A; + + // Definition of a resizable column-major dense Hermitian matrix based on HybridMatrix + blaze::HermitianMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense Hermitian matrix based on DynamicMatrix + blaze::HermitianMatrix< blaze::DynamicMatrix,rowMajor> > C; + + // Definition of a fixed-size row-major dense diagonal matrix based on CustomMatrix + blaze::HermitianMatrix< blaze::CustomMatrix > D; + + // Definition of a compressed row-major single precision complex Hermitian matrix + blaze::HermitianMatrix< blaze::CompressedMatrix,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 > A; // Both Hermitian and symmetric + SymmetricMatrix< DynamicMatrix > B; // Both Hermitian and symmetric + + // The following two matrices will behave differently + HermitianMatrix< DynamicMatrix< complex > > C; // Only Hermitian + SymmetricMatrix< DynamicMatrix< complex > > D; // Only symmetric + + // Block-structured Hermitian matrices are not allowed + HermitianMatrix< DynamicMatrix< DynamicVector > > E; // Compilation error! + SymmetricMatrix< DynamicMatrix< DynamicVector > > 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: +// +// -# \ref hermitianmatrix_square +// -# \ref hermitianmatrix_hermitian +// -# \ref hermitianmatrix_initialization +// +// \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,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,3UL,3UL,columnMajor> > A; + + // Compilation error: the provided matrix type is not a square matrix type + HermitianMatrix< StaticMatrix,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 cplx; + + // Default constructed, row-major 3x3 Hermitian compressed matrix + HermitianMatrix< CompressedMatrix > 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 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 > C( B ); // OK + + // Assignment of a non-Hermitian dense matrix + StaticMatrix 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 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 > 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 > 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 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 > 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 cplx; + + // Setup of two default 4x4 Hermitian matrices + HermitianMatrix< DynamicMatrix > A1( 4 ), A2( 4 ); + + // Setup of the 3x2 dynamic matrix + // + // ( (1,-1) (2, 5) ) + // B = ( (3, 0) (4,-6) ) + // ( (5, 0) (6, 0) ) + // + DynamicMatrix 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 A( 5, 5 ); + + // Default initialized, 5x5 row-major Hermitian dynamic matrix + HermitianMatrix< DynamicMatrix > 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 cplx; + + DynamicMatrix A( 3, 3 ); + CompressedMatrix B( 3, 3 ); + + HermitianMatrix< DynamicMatrix > C( 3 ); + HermitianMatrix< CompressedMatrix > D( 3 ); + + HermitianMatrix< HybridMatrix > E; + HermitianMatrix< StaticMatrix > 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 > A; // Both Hermitian and symmetric + HermitianMatrix< CompressedMatrix > B; // Both Hermitian and symmetric + DynamicMatrix 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 > A; // Hermitian and symmetric + CompressedVector x; + DynamicVector 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 > DynamicHermitian; + + DynamicHermitian A( 10UL ); // Both Hermitian and symmetric + Row 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 > > A, C; + DynamicMatrix 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 > 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::value // Storage order of the adapted matrix + , bool DF = IsDenseMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public DenseMatrix< HermitianMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the dense matrix. + typedef TransposeType_ TT; //!< Transpose type of the dense matrix. + typedef ElementType_ ET; //!< Element type of the dense matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef HermitianMatrix This; //!< Type of this HermitianMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this HermitianMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef HermitianMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef HermitianMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef SIMDType_ SIMDType; //!< SIMD type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef HermitianProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant matrix value. + typedef ConstPointer_ ConstPointer; //!< Pointer to a constant matrix value. + typedef ConstIterator_ 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::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_ ValueType; //!< Type of the underlying elements. + typedef HermitianProxy PointerType; //!< Pointer return type. + typedef HermitianProxy 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 > 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& 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 > 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, HermitianMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, HermitianMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsBuiltin< ElementType_ >, HermitianMatrix& > + operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, HermitianMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, HermitianMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsBuiltin< ElementType_ >, HermitianMatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, HermitianMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, HermitianMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsBuiltin< ElementType_ >, HermitianMatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline HermitianMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, HermitianMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& m, T ); + + template< typename MT2 > + inline TransExprTrait_ construct( const Matrix& m, TrueType ); + //@} + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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& m ); + + template< typename MT2, bool SO2 > + friend void invert2x2( HermitianMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invert3x3( HermitianMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invert4x4( HermitianMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invert5x5( HermitianMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invert6x6( HermitianMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invertByLU( HermitianMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invertByLDLT( HermitianMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invertByLDLH( HermitianMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invertByLLH( HermitianMatrix& 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::value == Columns::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::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::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 cplx; + typedef blaze::HermitianMatrix< blaze::StaticMatrix > 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::HermitianMatrix( initializer_list< initializer_list > 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 cplx; + + cplx* array = new cplx[16]; + // ... Initialization of the dynamic array + blaze::HermitianMatrix< blaze::DynamicMatrix > 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::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 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 > 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::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::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::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::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::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::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::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::HermitianMatrix( const Matrix& m ) + : matrix_( construct( m, typename IsBuiltin< ElementType_ >::Type() ) ) // The adapted dense matrix +{ + if( !IsHermitian::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::Reference + HermitianMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename HermitianMatrix::ConstReference + HermitianMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename HermitianMatrix::Reference + HermitianMatrix::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::ConstReference + HermitianMatrix::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::ConstPointer + HermitianMatrix::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::ConstPointer + HermitianMatrix::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::Iterator + HermitianMatrix::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::ConstIterator + HermitianMatrix::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::ConstIterator + HermitianMatrix::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::Iterator + HermitianMatrix::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::ConstIterator + HermitianMatrix::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::ConstIterator + HermitianMatrix::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 cplx; + + blaze::HermitianMatrix< blaze::StaticMatrix > 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& + HermitianMatrix::operator=( initializer_list< initializer_list > 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 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 > 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& + HermitianMatrix::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& + HermitianMatrix::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& + HermitianMatrix::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, HermitianMatrix& > + HermitianMatrix::operator=( const Matrix& rhs ) +{ + if( !IsHermitian::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, HermitianMatrix& > + HermitianMatrix::operator=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" ); + } + + if( IsHermitian::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_ >, HermitianMatrix& > + HermitianMatrix::operator=( const Matrix& 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, HermitianMatrix& > + HermitianMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsHermitian::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, HermitianMatrix& > + HermitianMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" ); + } + + if( IsHermitian::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ 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_ >, HermitianMatrix& > + HermitianMatrix::operator+=( const Matrix& 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, HermitianMatrix& > + HermitianMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsHermitian::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, HermitianMatrix& > + HermitianMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" ); + } + + if( IsHermitian::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ 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_ >, HermitianMatrix& > + HermitianMatrix::operator-=( const Matrix& 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& + HermitianMatrix::operator*=( const Matrix& 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, HermitianMatrix >& + HermitianMatrix::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, HermitianMatrix >& + HermitianMatrix::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::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::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::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::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::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::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::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::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 > > 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::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::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::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::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::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& HermitianMatrix::transpose() +{ + if( IsComplex::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& HermitianMatrix::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& + HermitianMatrix::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::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::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::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::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::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::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::SIMDType + HermitianMatrix::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::SIMDType + HermitianMatrix::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::SIMDType + HermitianMatrix::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::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 // Storage order of the adapted dense matrix +inline void + HermitianMatrix::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 // Storage order of the adapted dense matrix +inline void + HermitianMatrix::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 // Storage order of the adapted dense matrix +inline void + HermitianMatrix::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 // 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::construct( const Matrix& 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_ + HermitianMatrix::construct( const Matrix& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 cplx; + typedef blaze::HermitianMatrix< blaze::CompressedMatrix > 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_ ElementType; //!< Type of the represented matrix element. + typedef Iterator_ IteratorType; //!< Type of the underlying sparse matrix iterators. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef HermitianValue ValueType; //!< The value type of the value-index-pair. + typedef size_t IndexType; //!< The index type of the value-index-pair. + typedef HermitianValue Reference; //!< Reference return type. + typedef const HermitianValue 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::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& HermitianElement::operator=( const T& v ) +{ + if( IsComplex::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& HermitianElement::operator+=( const T& v ) +{ + if( IsComplex::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& HermitianElement::operator-=( const T& v ) +{ + if( IsComplex::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& HermitianElement::operator*=( const T& v ) +{ + if( IsComplex::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& HermitianElement::operator/=( const T& v ) +{ + if( IsComplex::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::Pointer HermitianElement::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::Reference HermitianElement::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::IndexType HermitianElement::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::sync() +{ + if( pos_->index() == index_ || isDefault( pos_->value() ) ) + return; + + const size_t row ( ( IsRowMajorMatrix::value )?( pos_->index() ):( index_ ) ); + const size_t column( ( IsRowMajorMatrix::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::isSynced() const +{ + const size_t row ( ( IsRowMajorMatrix::value )?( pos_->index() ):( index_ ) ); + const size_t column( ( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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 > +{ + 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_ RepresentedType; //!< Type of the represented matrix element. + typedef Reference_ Reference; //!< Reference to the represented element. + typedef ConstReference_ 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 + , ComplexType + , BuiltinType >::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::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::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& HermitianProxy::operator=( const HermitianProxy& hp ) +{ + typedef ElementType_ ET; + + if( IsComplex::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& HermitianProxy::operator=( const T& value ) +{ + typedef ElementType_ ET; + + if( IsComplex::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& HermitianProxy::operator+=( const T& value ) +{ + typedef ElementType_ ET; + + if( IsComplex::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& HermitianProxy::operator-=( const T& value ) +{ + typedef ElementType_ ET; + + if( IsComplex::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& HermitianProxy::operator*=( const T& value ) +{ + typedef ElementType_ ET; + + if( IsComplex::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& HermitianProxy::operator/=( const T& value ) +{ + typedef ElementType_ ET; + + if( IsComplex::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::Pointer HermitianProxy::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::ConstPointer HermitianProxy::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::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::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::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::ConstReference HermitianProxy::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::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::ValueType HermitianProxy::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::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::ValueType HermitianProxy::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::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& proxy ); + +template< typename MT > +inline void clear( const HermitianProxy& proxy ); + +template< typename MT > +inline void invert( const HermitianProxy& proxy ); + +template< typename MT > +inline bool isDefault( const HermitianProxy& proxy ); + +template< typename MT > +inline bool isReal( const HermitianProxy& proxy ); + +template< typename MT > +inline bool isZero( const HermitianProxy& proxy ); + +template< typename MT > +inline bool isOne( const HermitianProxy& proxy ); + +template< typename MT > +inline bool isnan( const HermitianProxy& 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& 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& 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& 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& 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& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 cplx; + typedef blaze::HermitianMatrix< blaze::CompressedMatrix > 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 > +{ + 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_ RepresentedType; //!< Type of the represented matrix element. + + //! Value type of the represented complex element. + typedef typename If_< IsComplex + , ComplexType + , BuiltinType >::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::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& HermitianValue::operator=( const HermitianValue& hv ) +{ + const bool isDiagonal( pos_->index() == index_ ); + + if( IsComplex::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& HermitianValue::operator=( const T& value ) +{ + const bool isDiagonal( pos_->index() == index_ ); + + if( IsComplex::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& HermitianValue::operator+=( const T& value ) +{ + const bool isDiagonal( pos_->index() == index_ ); + + if( IsComplex::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& HermitianValue::operator-=( const T& value ) +{ + const bool isDiagonal( pos_->index() == index_ ); + + if( IsComplex::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& HermitianValue::operator*=( const T& value ) +{ + const bool isDiagonal( pos_->index() == index_ ); + + if( IsComplex::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& HermitianValue::operator/=( const T& value ) +{ + const bool isDiagonal( pos_->index() == index_ ); + + if( IsComplex::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::reset() const +{ + using blaze::reset; + + reset( pos_->value() ); + + if( pos_->index() != index_ ) + { + const size_t row ( ( IsRowMajorMatrix::value )?( pos_->index() ):( index_ ) ); + const size_t column( ( IsRowMajorMatrix::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::clear() const +{ + using blaze::clear; + + clear( pos_->value() ); + + if( pos_->index() != index_ ) + { + const size_t row ( ( IsRowMajorMatrix::value )?( pos_->index() ):( index_ ) ); + const size_t column( ( IsRowMajorMatrix::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::invert() const +{ + using blaze::invert; + + invert( pos_->value() ); + + if( pos_->index() != index_ ) + { + const size_t row ( ( IsRowMajorMatrix::value )?( pos_->index() ):( index_ ) ); + const size_t column( ( IsRowMajorMatrix::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::RepresentedType HermitianValue::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::sync() const +{ + if( pos_->index() == index_ || isDefault( pos_->value() ) ) + return; + + const size_t row ( ( IsRowMajorMatrix::value )?( pos_->index() ):( index_ ) ); + const size_t column( ( IsRowMajorMatrix::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::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::ValueType HermitianValue::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::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::ValueType HermitianValue::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::imag( ValueType value ) const +{ + pos_->value().imag( value ); + sync(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name HermitianValue global functions */ +//@{ +template< typename MT > +inline void reset( const HermitianValue& value ); + +template< typename MT > +inline void clear( const HermitianValue& value ); + +template< typename MT > +inline void invert( const HermitianValue& value ); + +template< typename MT > +inline bool isDefault( const HermitianValue& value ); + +template< typename MT > +inline bool isReal( const HermitianValue& value ); + +template< typename MT > +inline bool isZero( const HermitianValue& value ); + +template< typename MT > +inline bool isOne( const HermitianValue& value ); + +template< typename MT > +inline bool isnan( const HermitianValue& 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& 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& 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& 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& 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& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public SparseMatrix< HermitianMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the sparse matrix. + typedef TransposeType_ TT; //!< Transpose type of the sparse matrix. + typedef ElementType_ ET; //!< Element type of the sparse matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef HermitianMatrix This; //!< Type of this HermitianMatrix instance. + typedef SparseMatrix BaseType; //!< Base type of this HermitianMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef HermitianMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef HermitianMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef HermitianProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef ConstIterator_ 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::Other > Other; + }; + //********************************************************************************************** + + //**Iterator class definition******************************************************************* + /*!\brief Iterator over the elements of the sparse Hermitian matrix. + */ + class Iterator + { + public: + //**Type definitions************************************************************************* + typedef Iterator_ IteratorType; //!< Type of the underlying sparse matrix iterators. + + typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category. + typedef HermitianElement 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& nonzeros ); + + inline HermitianMatrix( const HermitianMatrix& m ); + inline HermitianMatrix( HermitianMatrix&& m ) noexcept; + + template< typename MT2, bool SO2 > + inline HermitianMatrix( const Matrix& 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, HermitianMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, HermitianMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsBuiltin< ElementType_ >, HermitianMatrix& > + operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, HermitianMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, HermitianMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsBuiltin< ElementType_ >, HermitianMatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, HermitianMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, HermitianMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsBuiltin< ElementType_ >, HermitianMatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline HermitianMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, HermitianMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& m, T ); + + template< typename MT2 > + inline TransExprTrait_ construct( const Matrix& 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& 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::value == Columns::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::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::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::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::HermitianMatrix( size_t n, const std::vector& 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::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::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::HermitianMatrix( const Matrix& m ) + : matrix_( construct( m, typename IsBuiltin< ElementType_ >::Type() ) ) // The adapted sparse matrix +{ + if( !IsHermitian::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::Reference + HermitianMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename HermitianMatrix::ConstReference + HermitianMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename HermitianMatrix::Reference + HermitianMatrix::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::ConstReference + HermitianMatrix::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::Iterator + HermitianMatrix::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::ConstIterator + HermitianMatrix::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::ConstIterator + HermitianMatrix::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::Iterator + HermitianMatrix::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::ConstIterator + HermitianMatrix::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::ConstIterator + HermitianMatrix::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& + HermitianMatrix::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& + HermitianMatrix::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, HermitianMatrix& > + HermitianMatrix::operator=( const Matrix& rhs ) +{ + if( !IsHermitian::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, HermitianMatrix& > + HermitianMatrix::operator=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" ); + } + + if( IsHermitian::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_ >, HermitianMatrix& > + HermitianMatrix::operator=( const Matrix& 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, HermitianMatrix& > + HermitianMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsHermitian::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, HermitianMatrix& > + HermitianMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" ); + } + + if( IsHermitian::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ 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_ >, HermitianMatrix& > + HermitianMatrix::operator+=( const Matrix& 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, HermitianMatrix& > + HermitianMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsHermitian::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, HermitianMatrix& > + HermitianMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to Hermitian matrix" ); + } + + if( IsHermitian::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ 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_ >, HermitianMatrix& > + HermitianMatrix::operator-=( const Matrix& 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& + HermitianMatrix::operator*=( const Matrix& 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, HermitianMatrix >& + HermitianMatrix::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, HermitianMatrix >& + HermitianMatrix::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::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::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::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::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::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::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::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 > 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::reset( size_t i ) +{ + for( Iterator_ it=matrix_.begin(i); it!=matrix_.end(i); ++it ) + { + const size_t j( it->index() ); + + if( i == j ) + continue; + + if( SO ) { + const Iterator_ pos( matrix_.find( i, j ) ); + BLAZE_INTERNAL_ASSERT( pos != matrix_.end( j ), "Missing element detected" ); + matrix_.erase( j, pos ); + } + else { + const Iterator_ 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::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::Iterator + HermitianMatrix::set( size_t i, size_t j, const ElementType& value ) +{ + const bool isDiagonal( i == j ); + + if( IsComplex::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::Iterator + HermitianMatrix::insert( size_t i, size_t j, const ElementType& value ) +{ + const bool isDiagonal( i == j ); + + if( IsComplex::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::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::Iterator + HermitianMatrix::erase( size_t i, Iterator pos ) +{ + const Iterator_ 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::Iterator + HermitianMatrix::erase( size_t i, Iterator first, Iterator last ) +{ + for( Iterator_ 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::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::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::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::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::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& HermitianMatrix::transpose() +{ + if( IsComplex::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& HermitianMatrix::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& + HermitianMatrix::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& + HermitianMatrix::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::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::Iterator + HermitianMatrix::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::ConstIterator + HermitianMatrix::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::Iterator + HermitianMatrix::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::ConstIterator + HermitianMatrix::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::Iterator + HermitianMatrix::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::ConstIterator + HermitianMatrix::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 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 > 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::append( size_t i, size_t j, const ElementType& value, bool check ) +{ + const bool isDiagonal( i == j ); + + if( IsComplex::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::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::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::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::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::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::construct( const Matrix& 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_ + HermitianMatrix::construct( const Matrix& 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 +#include + + +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 > A; + + // Definition of a resizable column-major dense lower matrix based on HybridMatrix + blaze::LowerMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense lower matrix based on DynamicMatrix + blaze::LowerMatrix< blaze::DynamicMatrix > C; + + // Definition of a fixed-size row-major dense lower matrix based on CustomMatrix + blaze::LowerMatrix< blaze::CustomMatrix > D; + + // Definition of a compressed row-major single precision lower matrix + blaze::LowerMatrix< blaze::CompressedMatrix > 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: +// +// -# \ref lowermatrix_square +// -# \ref lowermatrix_lower +// -# \ref lowermatrix_initialization +// -# \ref lowermatrix_storage +// +// \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 > 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 > A; + + // Compilation error: the provided matrix type is not a square matrix type + LowerMatrix< StaticMatrix > 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 > 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 B( 3.0, 0.0, 0.0, + 8.0, 0.0, 0.0, + -2.0, -1.0, 4.0 ); + + LowerMatrix< DynamicMatrix > C( B ); // OK + + // Assignment of a non-lower dense matrix + StaticMatrix 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 > 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 > 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 > A1( 4 ), A2( 4 ); + + // Setup of a 4-dimensional vector + // + // v = ( 1 2 3 0 ) + // + DynamicVector 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 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 A( 5, 5 ); + + // 5x5 row-major lower dynamic matrix with default initialized upper matrix + LowerMatrix< DynamicMatrix > 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 A( 3, 3 ); + CompressedMatrix B( 3, 3 ); + + LowerMatrix< DynamicMatrix > C( 3 ); + LowerMatrix< CompressedMatrix > D( 3 ); + + LowerMatrix< HybridMatrix > E; + LowerMatrix< StaticMatrix > 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 > > 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 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 > A; + LowerMatrix< DynamicMatrix > B; + DynamicMatrix 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 > A; + DynamicVector 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 > A, C; + DynamicMatrix 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 > 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::value // Storage order of the adapted matrix + , bool DF = IsDenseMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public DenseMatrix< LowerMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the dense matrix. + typedef TransposeType_ TT; //!< Transpose type of the dense matrix. + typedef ElementType_ ET; //!< Element type of the dense matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef LowerMatrix This; //!< Type of this LowerMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this LowerMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef LowerMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef UpperMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef SIMDType_ SIMDType; //!< SIMD type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef LowerProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant matrix value. + typedef ConstPointer_ ConstPointer; //!< Pointer to a constant matrix value. + typedef ConstIterator_ 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::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_ ValueType; //!< Type of the underlying elements. + typedef LowerProxy PointerType; //!< Pointer return type. + typedef LowerProxy 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 > 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 > 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, LowerMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, LowerMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, LowerMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, LowerMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, LowerMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, LowerMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline LowerMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, LowerMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& 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& m ); + + template< typename MT2, bool SO2, bool DF2 > + friend MT2& derestrict( LowerMatrix& 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::value == Columns::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::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::LowerMatrix( const A1& a1 ) + : matrix_( construct( a1, typename IsResizable::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::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 > 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::LowerMatrix( initializer_list< initializer_list > 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 > 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::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 > 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::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::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::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::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::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::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::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::Reference + LowerMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename LowerMatrix::ConstReference + LowerMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename LowerMatrix::Reference + LowerMatrix::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::ConstReference + LowerMatrix::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::ConstPointer + LowerMatrix::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::ConstPointer + LowerMatrix::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::Iterator + LowerMatrix::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::ConstIterator + LowerMatrix::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::ConstIterator + LowerMatrix::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::Iterator + LowerMatrix::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::ConstIterator + LowerMatrix::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::ConstIterator + LowerMatrix::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& + LowerMatrix::operator=( const ElementType& rhs ) +{ + if( SO ) { + for( size_t j=0UL; j > 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& + LowerMatrix::operator=( initializer_list< initializer_list > 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 > 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& + LowerMatrix::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& + LowerMatrix::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& + LowerMatrix::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, LowerMatrix& > + LowerMatrix::operator=( const Matrix& rhs ) +{ + if( !IsLower::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, LowerMatrix& > + LowerMatrix::operator=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" ); + } + + if( IsLower::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, LowerMatrix& > + LowerMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsLower::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, LowerMatrix& > + LowerMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" ); + } + + if( IsLower::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ 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, LowerMatrix& > + LowerMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsLower::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, LowerMatrix& > + LowerMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" ); + } + + if( IsLower::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ 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& + LowerMatrix::operator*=( const Matrix& 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, LowerMatrix >& + LowerMatrix::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, LowerMatrix >& + LowerMatrix::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::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::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::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::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::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::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::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::reset() +{ + using blaze::clear; + + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted dense matrix +inline void LowerMatrix::reset( size_t i ) +{ + using blaze::clear; + + if( SO ) { + for( size_t j=i; j // Storage order of the adapted dense matrix +inline void LowerMatrix::clear() +{ + using blaze::clear; + + if( IsResizable::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::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::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::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& LowerMatrix::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::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::maxNonZeros() noexcept +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + return maxNonZeros( Rows::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::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::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::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::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::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::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::SIMDType + LowerMatrix::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::SIMDType + LowerMatrix::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::SIMDType + LowerMatrix::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::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::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 // 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::construct( const Matrix& m, T ) +{ + const MT tmp( ~m ); + + if( !IsLower::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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, ElementType_ > +{ + private: + //**Type definitions**************************************************************************** + //! Reference type of the underlying matrix type. + typedef AddConst_< Reference_ > ReferenceType; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef ElementType_ RepresentedType; //!< Type of the represented matrix element. + typedef AddReference_ 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 list ) const; + + template< typename T > + inline const LowerProxy& operator=( initializer_list< initializer_list > 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::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::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& LowerProxy::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& LowerProxy::operator=( initializer_list 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& LowerProxy::operator=( initializer_list< initializer_list > 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& LowerProxy::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& LowerProxy::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& LowerProxy::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& LowerProxy::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& LowerProxy::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::RawReference LowerProxy::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::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::operator ConstReference() const noexcept +{ + return static_cast( value_ ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LowerProxy global functions */ +//@{ +template< typename MT > +inline void reset( const LowerProxy& proxy ); + +template< typename MT > +inline void clear( const LowerProxy& proxy ); + +template< typename MT > +inline bool isDefault( const LowerProxy& proxy ); + +template< typename MT > +inline bool isReal( const LowerProxy& proxy ); + +template< typename MT > +inline bool isZero( const LowerProxy& proxy ); + +template< typename MT > +inline bool isOne( const LowerProxy& proxy ); + +template< typename MT > +inline bool isnan( const LowerProxy& 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& 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& 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& 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& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public SparseMatrix< LowerMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the sparse matrix. + typedef TransposeType_ TT; //!< Transpose type of the sparse matrix. + typedef ElementType_ ET; //!< Element type of the sparse matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef LowerMatrix This; //!< Type of this LowerMatrix instance. + typedef SparseMatrix BaseType; //!< Base type of this LowerMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef LowerMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef UpperMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef LowerProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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::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& nonzeros ); + + inline LowerMatrix( const LowerMatrix& m ); + inline LowerMatrix( LowerMatrix&& m ) noexcept; + + template< typename MT2, bool SO2 > + inline LowerMatrix( const Matrix& 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, LowerMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, LowerMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, LowerMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, LowerMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, LowerMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, LowerMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline LowerMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, LowerMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& m ); + + template< typename MT2, bool SO2, bool DF2 > + friend MT2& derestrict( LowerMatrix& 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::value == Columns::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::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::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::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::LowerMatrix( size_t n, const std::vector& 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::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::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::LowerMatrix( const Matrix& m ) + : matrix_( ~m ) // The adapted sparse matrix +{ + if( !IsLower::value && !isLower( matrix_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of lower matrix" ); + } + + if( !IsLower::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::Reference + LowerMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename LowerMatrix::ConstReference + LowerMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename LowerMatrix::Reference + LowerMatrix::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::ConstReference + LowerMatrix::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::Iterator + LowerMatrix::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::ConstIterator + LowerMatrix::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::ConstIterator + LowerMatrix::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::Iterator + LowerMatrix::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::ConstIterator + LowerMatrix::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::ConstIterator + LowerMatrix::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& + LowerMatrix::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& + LowerMatrix::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, LowerMatrix& > + LowerMatrix::operator=( const Matrix& rhs ) +{ + if( !IsLower::value && !isLower( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" ); + } + + matrix_ = ~rhs; + + if( !IsLower::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, LowerMatrix& > + LowerMatrix::operator=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" ); + } + + if( IsLower::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::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, LowerMatrix& > + LowerMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsLower::value && !isLower( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" ); + } + + matrix_ += ~rhs; + + if( !IsLower::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, LowerMatrix& > + LowerMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" ); + } + + if( IsLower::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ tmp( ~rhs ); + + if( !isLower( tmp ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" ); + } + + matrix_ += tmp; + } + + if( !IsLower::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, LowerMatrix& > + LowerMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsLower::value && !isLower( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" ); + } + + matrix_ -= ~rhs; + + if( !IsLower::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, LowerMatrix& > + LowerMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" ); + } + + if( IsLower::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ tmp( ~rhs ); + + if( !isLower( tmp ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to lower matrix" ); + } + + matrix_ -= tmp; + } + + if( !IsLower::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& + LowerMatrix::operator*=( const Matrix& 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::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, LowerMatrix >& + LowerMatrix::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, LowerMatrix >& + LowerMatrix::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::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::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::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::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::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::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::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::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::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::Iterator + LowerMatrix::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::Iterator + LowerMatrix::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::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::Iterator + LowerMatrix::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::Iterator + LowerMatrix::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::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::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::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::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::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& + LowerMatrix::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& + LowerMatrix::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::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::maxNonZeros() noexcept +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + return maxNonZeros( Rows::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::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::resetUpper() +{ + if( SO ) { + for( size_t j=1UL; j // Storage order of the adapted sparse matrix +inline typename LowerMatrix::Iterator + LowerMatrix::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::ConstIterator + LowerMatrix::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::Iterator + LowerMatrix::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::ConstIterator + LowerMatrix::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::Iterator + LowerMatrix::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::ConstIterator + LowerMatrix::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 > 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::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::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::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::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::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::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 +#include + + +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 > A; + + // Definition of a resizable column-major dense strictly lower matrix based on HybridMatrix + blaze::StrictlyLowerMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense strictly lower matrix based on DynamicMatrix + blaze::StrictlyLowerMatrix< blaze::DynamicMatrix > C; + + // Definition of a fixed-size row-major dense strictly lower matrix based on CustomMatrix + blaze::StrictlyLowerMatrix< blaze::CustomMatrix > D; + + // Definition of a compressed row-major single precision strictly lower matrix + blaze::StrictlyLowerMatrix< blaze::CompressedMatrix > 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: +// +// -# \ref strictlylowermatrix_square +// -# \ref strictlylowermatrix_strictlylower +// -# \ref strictlylowermatrix_initialization +// -# \ref strictlylowermatrix_storage +// +// \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 > 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 > A; + + // Compilation error: the provided matrix type is not a square matrix type + StrictlyLowerMatrix< StaticMatrix > 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 > 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 B( 0.0, 0.0, 0.0, + 8.0, 0.0, 0.0, + -2.0, -1.0, 0.0 ); + + StrictlyLowerMatrix< DynamicMatrix > C( B ); // OK + + // Assignment of a general dense matrix + StaticMatrix 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 > 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 > 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 > A1( 4 ), A2( 4 ); + + // Setup of a 4-dimensional vector + // + // v = ( 3 2 0 0 ) + // + DynamicVector 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 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 A( 5, 5 ); + + // 5x5 row-major strictly lower dynamic matrix with default initialized diagonal and upper matrix + StrictlyLowerMatrix< DynamicMatrix > 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 A( 3, 3 ); + CompressedMatrix B( 3, 3 ); + + StrictlyLowerMatrix< DynamicMatrix > C( 3 ); + StrictlyLowerMatrix< CompressedMatrix > D( 3 ); + + StrictlyLowerMatrix< HybridMatrix > E; + StrictlyLowerMatrix< StaticMatrix > 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 > > 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 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 > A; + StrictlyLowerMatrix< DynamicMatrix > B; + DynamicMatrix 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 > A; + DynamicVector 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 > A, C; + DynamicMatrix 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 > 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::value // Storage order of the adapted matrix + , bool DF = IsDenseMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public DenseMatrix< StrictlyLowerMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the dense matrix. + typedef TransposeType_ TT; //!< Transpose type of the dense matrix. + typedef ElementType_ ET; //!< Element type of the dense matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef StrictlyLowerMatrix This; //!< Type of this StrictlyLowerMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this StrictlyLowerMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef StrictlyLowerMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef StrictlyUpperMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef SIMDType_ SIMDType; //!< SIMD type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef StrictlyLowerProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant matrix value. + typedef ConstPointer_ ConstPointer; //!< Pointer to a constant matrix value. + typedef ConstIterator_ 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::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_ ValueType; //!< Type of the underlying elements. + typedef StrictlyLowerProxy PointerType; //!< Pointer return type. + typedef StrictlyLowerProxy 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 > 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 > 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, StrictlyLowerMatrix& > + operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, StrictlyLowerMatrix& > + operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, StrictlyLowerMatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, StrictlyLowerMatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, StrictlyLowerMatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, StrictlyLowerMatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline StrictlyLowerMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, StrictlyLowerMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& 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& 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::value == Columns::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::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::StrictlyLowerMatrix( const A1& a1 ) + : matrix_( construct( a1, typename IsResizable::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::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 > 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::StrictlyLowerMatrix( initializer_list< initializer_list > 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 > 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::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 > 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::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::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::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::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::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::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::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::Reference + StrictlyLowerMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename StrictlyLowerMatrix::ConstReference + StrictlyLowerMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename StrictlyLowerMatrix::Reference + StrictlyLowerMatrix::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::ConstReference + StrictlyLowerMatrix::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::ConstPointer + StrictlyLowerMatrix::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::ConstPointer + StrictlyLowerMatrix::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::Iterator + StrictlyLowerMatrix::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::ConstIterator + StrictlyLowerMatrix::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::ConstIterator + StrictlyLowerMatrix::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::Iterator + StrictlyLowerMatrix::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::ConstIterator + StrictlyLowerMatrix::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::ConstIterator + StrictlyLowerMatrix::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& + StrictlyLowerMatrix::operator=( const ElementType& rhs ) +{ + if( SO ) { + for( size_t j=0UL; j > 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& + StrictlyLowerMatrix::operator=( initializer_list< initializer_list > 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 > 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& + StrictlyLowerMatrix::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& + StrictlyLowerMatrix::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& + StrictlyLowerMatrix::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, StrictlyLowerMatrix& > + StrictlyLowerMatrix::operator=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || + ( !IsStrictlyLower::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, StrictlyLowerMatrix& > + StrictlyLowerMatrix::operator=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" ); + } + + if( IsStrictlyLower::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, StrictlyLowerMatrix& > + StrictlyLowerMatrix::operator+=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || + ( !IsStrictlyLower::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, StrictlyLowerMatrix& > + StrictlyLowerMatrix::operator+=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" ); + } + + if( IsStrictlyLower::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ 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, StrictlyLowerMatrix& > + StrictlyLowerMatrix::operator-=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || + ( !IsStrictlyLower::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, StrictlyLowerMatrix& > + StrictlyLowerMatrix::operator-=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" ); + } + + if( IsStrictlyLower::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ 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& + StrictlyLowerMatrix::operator*=( const Matrix& 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, StrictlyLowerMatrix >& + StrictlyLowerMatrix::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, StrictlyLowerMatrix >& + StrictlyLowerMatrix::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::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::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::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::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::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::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::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::reset() +{ + using blaze::clear; + + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted dense matrix +inline void StrictlyLowerMatrix::reset( size_t i ) +{ + using blaze::clear; + + if( SO ) { + for( size_t j=i+1UL; j // Storage order of the adapted dense matrix +inline void StrictlyLowerMatrix::clear() +{ + using blaze::clear; + + if( IsResizable::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::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::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::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& + StrictlyLowerMatrix::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::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::maxNonZeros() noexcept +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + return maxNonZeros( Rows::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::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::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::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::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::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::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::SIMDType + StrictlyLowerMatrix::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::SIMDType + StrictlyLowerMatrix::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::SIMDType + StrictlyLowerMatrix::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::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::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 // 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::construct( const Matrix& m, T ) +{ + const MT tmp( ~m ); + + if( IsUniTriangular::value || + ( !IsStrictlyLower::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public SparseMatrix< StrictlyLowerMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the sparse matrix. + typedef TransposeType_ TT; //!< Transpose type of the sparse matrix. + typedef ElementType_ ET; //!< Element type of the sparse matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef StrictlyLowerMatrix This; //!< Type of this StrictlyLowerMatrix instance. + typedef SparseMatrix BaseType; //!< Base type of this StrictlyLowerMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef StrictlyLowerMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef StrictlyUpperMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef StrictlyLowerProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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::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& nonzeros ); + + inline StrictlyLowerMatrix( const StrictlyLowerMatrix& m ); + inline StrictlyLowerMatrix( StrictlyLowerMatrix&& m ) noexcept; + + template< typename MT2, bool SO2 > + inline StrictlyLowerMatrix( const Matrix& 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, StrictlyLowerMatrix& > + operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, StrictlyLowerMatrix& > + operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, StrictlyLowerMatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, StrictlyLowerMatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, StrictlyLowerMatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, StrictlyLowerMatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline StrictlyLowerMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, StrictlyLowerMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& 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::value == Columns::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::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::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::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::StrictlyLowerMatrix( size_t n, const std::vector& 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::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::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::StrictlyLowerMatrix( const Matrix& m ) + : matrix_( ~m ) // The adapted sparse matrix +{ + if( IsUniTriangular::value || + ( !IsStrictlyLower::value && !isStrictlyLower( matrix_ ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly lower matrix" ); + } + + if( !IsStrictlyLower::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::Reference + StrictlyLowerMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename StrictlyLowerMatrix::ConstReference + StrictlyLowerMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename StrictlyLowerMatrix::Reference + StrictlyLowerMatrix::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::ConstReference + StrictlyLowerMatrix::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::Iterator + StrictlyLowerMatrix::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::ConstIterator + StrictlyLowerMatrix::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::ConstIterator + StrictlyLowerMatrix::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::Iterator + StrictlyLowerMatrix::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::ConstIterator + StrictlyLowerMatrix::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::ConstIterator + StrictlyLowerMatrix::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& + StrictlyLowerMatrix::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& + StrictlyLowerMatrix::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, StrictlyLowerMatrix& > + StrictlyLowerMatrix::operator=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || + ( !IsStrictlyLower::value && !isStrictlyLower( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" ); + } + + matrix_ = ~rhs; + + if( !IsStrictlyLower::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, StrictlyLowerMatrix& > + StrictlyLowerMatrix::operator=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" ); + } + + if( IsStrictlyLower::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::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, StrictlyLowerMatrix& > + StrictlyLowerMatrix::operator+=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || + ( !IsStrictlyLower::value && !isStrictlyLower( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" ); + } + + matrix_ += ~rhs; + + if( !IsStrictlyLower::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, StrictlyLowerMatrix& > + StrictlyLowerMatrix::operator+=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" ); + } + + if( IsStrictlyLower::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ tmp( ~rhs ); + + if( !isStrictlyLower( tmp ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" ); + } + + matrix_ += tmp; + } + + if( !IsStrictlyLower::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, StrictlyLowerMatrix& > + StrictlyLowerMatrix::operator-=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || + ( !IsStrictlyLower::value && !isStrictlyLower( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" ); + } + + matrix_ -= ~rhs; + + if( !IsStrictlyLower::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, StrictlyLowerMatrix& > + StrictlyLowerMatrix::operator-=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" ); + } + + if( IsStrictlyLower::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ tmp( ~rhs ); + + if( !isStrictlyLower( tmp ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly lower matrix" ); + } + + matrix_ -= tmp; + } + + if( !IsStrictlyLower::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& + StrictlyLowerMatrix::operator*=( const Matrix& 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::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, StrictlyLowerMatrix >& + StrictlyLowerMatrix::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, StrictlyLowerMatrix >& + StrictlyLowerMatrix::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::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::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::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::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::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::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::reset() +{ + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted sparse matrix +inline void StrictlyLowerMatrix::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::clear() +{ + using blaze::clear; + + if( IsResizable::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::Iterator + StrictlyLowerMatrix::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::Iterator + StrictlyLowerMatrix::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::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::Iterator + StrictlyLowerMatrix::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::Iterator + StrictlyLowerMatrix::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::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::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::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::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::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& + StrictlyLowerMatrix::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& + StrictlyLowerMatrix::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::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::maxNonZeros() noexcept +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + return maxNonZeros( Rows::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::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::resetUpper() +{ + if( SO ) { + for( size_t j=1UL; j // Storage order of the adapted sparse matrix +inline typename StrictlyLowerMatrix::Iterator + StrictlyLowerMatrix::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::ConstIterator + StrictlyLowerMatrix::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::Iterator + StrictlyLowerMatrix::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::ConstIterator + StrictlyLowerMatrix::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::Iterator + StrictlyLowerMatrix::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::ConstIterator + StrictlyLowerMatrix::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 > 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::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::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::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::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::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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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, ElementType_ > +{ + private: + //**Type definitions**************************************************************************** + //! Reference type of the underlying matrix type. + typedef AddConst_< Reference_ > ReferenceType; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef ElementType_ RepresentedType; //!< Type of the represented matrix element. + typedef AddReference_ 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 list ) const; + + template< typename T > + inline const StrictlyLowerProxy& operator=( initializer_list< initializer_list > 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::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::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& + StrictlyLowerProxy::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& + StrictlyLowerProxy::operator=( initializer_list 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& + StrictlyLowerProxy::operator=( initializer_list< initializer_list > 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& StrictlyLowerProxy::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& StrictlyLowerProxy::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& StrictlyLowerProxy::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& StrictlyLowerProxy::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& StrictlyLowerProxy::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::RawReference StrictlyLowerProxy::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::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::operator ConstReference() const noexcept +{ + return static_cast( value_ ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name StrictlyLowerProxy global functions */ +//@{ +template< typename MT > +inline void reset( const StrictlyLowerProxy& proxy ); + +template< typename MT > +inline void clear( const StrictlyLowerProxy& proxy ); + +template< typename MT > +inline bool isDefault( const StrictlyLowerProxy& proxy ); + +template< typename MT > +inline bool isReal( const StrictlyLowerProxy& proxy ); + +template< typename MT > +inline bool isZero( const StrictlyLowerProxy& proxy ); + +template< typename MT > +inline bool isOne( const StrictlyLowerProxy& proxy ); + +template< typename MT > +inline bool isnan( const StrictlyLowerProxy& 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& 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& 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& 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& 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& 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& 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& 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 +#include + + +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 > A; + + // Definition of a resizable column-major dense strictly upper matrix based on HybridMatrix + blaze::StrictlyUpperMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense strictly upper matrix based on DynamicMatrix + blaze::StrictlyUpperMatrix< blaze::DynamicMatrix > C; + + // Definition of a fixed-size row-major dense strictly upper matrix based on CustomMatrix + blaze::StrictlyUpperMatrix< blaze::CustomMatrix > D; + + // Definition of a compressed row-major single precision strictly upper matrix + blaze::StrictlyUpperMatrix< blaze::CompressedMatrix > 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: +// +// -# \ref strictlyuppermatrix_square +// -# \ref strictlyuppermatrix_strictlyupper +// -# \ref strictlyuppermatrix_initialization +// -# \ref strictlyuppermatrix_storage +// +// \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 > 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 > A; + + // Compilation error: the provided matrix type is not a square matrix type + StrictlyUpperMatrix< StaticMatrix > 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 > 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 B( { { 0.0, 8.0, -2.0 }, + { 0.0, 0.0, -1.0 }, + { 0.0, 0.0, 0.0 } } ); + + StrictlyUpperMatrix< DynamicMatrix > C( B ); // OK + + // Assignment of a general dense matrix + StaticMatrix 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 > 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 > 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 > A1( 4 ), A2( 4 ); + + // Setup of a 4-dimensional vector + // + // v = ( 0 0 2 3 ) + // + DynamicVector 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 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 A( 5, 5 ); + + // 5x5 row-major strictly upper dynamic matrix with default initialized lower matrix + StrictlyUpperMatrix< DynamicMatrix > 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 A( 3, 3 ); + CompressedMatrix B( 3, 3 ); + + StrictlyUpperMatrix< DynamicMatrix > C( 3 ); + StrictlyUpperMatrix< CompressedMatrix > D( 3 ); + + StrictlyUpperMatrix< HybridMatrix > E; + StrictlyUpperMatrix< StaticMatrix > 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 > > 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 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 > A; + StrictlyUpperMatrix< DynamicMatrix > B; + DynamicMatrix 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 > A; + DynamicVector 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 > A, C; + DynamicMatrix 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 > 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::value // Storage order of the adapted matrix + , bool DF = IsDenseMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public DenseMatrix< StrictlyUpperMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the dense matrix. + typedef TransposeType_ TT; //!< Transpose type of the dense matrix. + typedef ElementType_ ET; //!< Element type of the dense matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef StrictlyUpperMatrix This; //!< Type of this StrictlyUpperMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this StrictlyUpperMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef StrictlyUpperMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef StrictlyLowerMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef SIMDType_ SIMDType; //!< SIMD type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef StrictlyUpperProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant matrix value. + typedef ConstPointer_ ConstPointer; //!< Pointer to a constant matrix value. + typedef ConstIterator_ 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::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_ ValueType; //!< Type of the underlying elements. + typedef StrictlyUpperProxy PointerType; //!< Pointer return type. + typedef StrictlyUpperProxy 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 > 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 > 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, StrictlyUpperMatrix& > + operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, StrictlyUpperMatrix& > + operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, StrictlyUpperMatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, StrictlyUpperMatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, StrictlyUpperMatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, StrictlyUpperMatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline StrictlyUpperMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, StrictlyUpperMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& 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& 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::value == Columns::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::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::StrictlyUpperMatrix( const A1& a1 ) + : matrix_( construct( a1, typename IsResizable::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::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 > 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::StrictlyUpperMatrix( initializer_list< initializer_list > 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 > 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::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 > 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::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::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::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::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::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::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::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::Reference + StrictlyUpperMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename StrictlyUpperMatrix::ConstReference + StrictlyUpperMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename StrictlyUpperMatrix::Reference + StrictlyUpperMatrix::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::ConstReference + StrictlyUpperMatrix::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::ConstPointer + StrictlyUpperMatrix::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::ConstPointer + StrictlyUpperMatrix::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::Iterator + StrictlyUpperMatrix::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::ConstIterator + StrictlyUpperMatrix::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::ConstIterator + StrictlyUpperMatrix::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::Iterator + StrictlyUpperMatrix::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::ConstIterator + StrictlyUpperMatrix::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::ConstIterator + StrictlyUpperMatrix::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& + StrictlyUpperMatrix::operator=( const ElementType& rhs ) +{ + if( SO ) { + for( size_t j=1UL; j > 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& + StrictlyUpperMatrix::operator=( initializer_list< initializer_list > 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 > 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& + StrictlyUpperMatrix::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& + StrictlyUpperMatrix::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& + StrictlyUpperMatrix::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, StrictlyUpperMatrix& > + StrictlyUpperMatrix::operator=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || + ( !IsStrictlyUpper::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, StrictlyUpperMatrix& > + StrictlyUpperMatrix::operator=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" ); + } + + if( IsStrictlyUpper::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, StrictlyUpperMatrix& > + StrictlyUpperMatrix::operator+=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || + ( !IsStrictlyUpper::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, StrictlyUpperMatrix& > + StrictlyUpperMatrix::operator+=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" ); + } + + if( IsStrictlyUpper::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ 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, StrictlyUpperMatrix& > + StrictlyUpperMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsStrictlyUpper::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, StrictlyUpperMatrix& > + StrictlyUpperMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" ); + } + + if( IsStrictlyUpper::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ 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& + StrictlyUpperMatrix::operator*=( const Matrix& 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, StrictlyUpperMatrix >& + StrictlyUpperMatrix::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, StrictlyUpperMatrix >& + StrictlyUpperMatrix::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::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::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::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::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::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::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::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::reset() +{ + using blaze::clear; + + if( SO ) { + for( size_t j=1UL; j // Storage order of the adapted dense matrix +inline void StrictlyUpperMatrix::reset( size_t i ) +{ + using blaze::clear; + + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted dense matrix +inline void StrictlyUpperMatrix::clear() +{ + using blaze::clear; + + if( IsResizable::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::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::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::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& + StrictlyUpperMatrix::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::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::maxNonZeros() noexcept +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + return maxNonZeros( Rows::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::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::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::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::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::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::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::SIMDType + StrictlyUpperMatrix::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::SIMDType + StrictlyUpperMatrix::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::SIMDType + StrictlyUpperMatrix::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::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::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 // 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::construct( const Matrix& m, T ) +{ + const MT tmp( ~m ); + + if( IsUniTriangular::value || + ( !IsStrictlyUpper::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public SparseMatrix< StrictlyUpperMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the sparse matrix. + typedef TransposeType_ TT; //!< Transpose type of the sparse matrix. + typedef ElementType_ ET; //!< Element type of the sparse matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef StrictlyUpperMatrix This; //!< Type of this StrictlyUpperMatrix instance. + typedef SparseMatrix BaseType; //!< Base type of this StrictlyUpperMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef StrictlyUpperMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef StrictlyLowerMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef StrictlyUpperProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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::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& nonzeros ); + + inline StrictlyUpperMatrix( const StrictlyUpperMatrix& m ); + inline StrictlyUpperMatrix( StrictlyUpperMatrix&& m ) noexcept; + + template< typename MT2, bool SO2 > + inline StrictlyUpperMatrix( const Matrix& 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, StrictlyUpperMatrix& > + operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, StrictlyUpperMatrix& > + operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, StrictlyUpperMatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, StrictlyUpperMatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, StrictlyUpperMatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, StrictlyUpperMatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline StrictlyUpperMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, StrictlyUpperMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& 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::value == Columns::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::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::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::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::StrictlyUpperMatrix( size_t n, const std::vector& 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::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::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::StrictlyUpperMatrix( const Matrix& m ) + : matrix_( ~m ) // The adapted sparse matrix +{ + if( IsUniTriangular::value || + ( !IsStrictlyUpper::value && !isStrictlyUpper( matrix_ ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of strictly upper matrix" ); + } + + if( !IsStrictlyUpper::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::Reference + StrictlyUpperMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename StrictlyUpperMatrix::ConstReference + StrictlyUpperMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename StrictlyUpperMatrix::Reference + StrictlyUpperMatrix::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::ConstReference + StrictlyUpperMatrix::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::Iterator + StrictlyUpperMatrix::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::ConstIterator + StrictlyUpperMatrix::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::ConstIterator + StrictlyUpperMatrix::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::Iterator + StrictlyUpperMatrix::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::ConstIterator + StrictlyUpperMatrix::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::ConstIterator + StrictlyUpperMatrix::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& + StrictlyUpperMatrix::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& + StrictlyUpperMatrix::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, StrictlyUpperMatrix& > + StrictlyUpperMatrix::operator=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || + ( !IsStrictlyUpper::value && !isStrictlyUpper( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" ); + } + + matrix_ = ~rhs; + + if( !IsStrictlyUpper::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, StrictlyUpperMatrix& > + StrictlyUpperMatrix::operator=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" ); + } + + if( IsStrictlyUpper::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::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, StrictlyUpperMatrix& > + StrictlyUpperMatrix::operator+=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || + ( !IsStrictlyUpper::value && !isStrictlyUpper( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" ); + } + + matrix_ += ~rhs; + + if( !IsStrictlyUpper::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, StrictlyUpperMatrix& > + StrictlyUpperMatrix::operator+=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || ( IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" ); + } + + if( IsStrictlyUpper::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ tmp( ~rhs ); + + if( !isStrictlyUpper( tmp ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" ); + } + + matrix_ += tmp; + } + + if( !IsStrictlyUpper::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, StrictlyUpperMatrix& > + StrictlyUpperMatrix::operator-=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || + ( !IsStrictlyUpper::value && !isStrictlyUpper( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" ); + } + + matrix_ -= ~rhs; + + if( !IsStrictlyUpper::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, StrictlyUpperMatrix& > + StrictlyUpperMatrix::operator-=( const Matrix& rhs ) +{ + if( IsUniTriangular::value || ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" ); + } + + if( IsStrictlyUpper::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ tmp( ~rhs ); + + if( !isStrictlyUpper( tmp ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to strictly upper matrix" ); + } + + matrix_ -= tmp; + } + + if( !IsStrictlyUpper::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& + StrictlyUpperMatrix::operator*=( const Matrix& 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::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, StrictlyUpperMatrix >& + StrictlyUpperMatrix::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, StrictlyUpperMatrix >& + StrictlyUpperMatrix::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::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::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::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::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::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::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::reset() +{ + if( SO ) { + for( size_t j=1UL; j // Storage order of the adapted sparse matrix +inline void StrictlyUpperMatrix::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::clear() +{ + using blaze::clear; + + if( IsResizable::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::Iterator + StrictlyUpperMatrix::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::Iterator + StrictlyUpperMatrix::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::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::Iterator + StrictlyUpperMatrix::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::Iterator + StrictlyUpperMatrix::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::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::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::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::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::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& + StrictlyUpperMatrix::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& + StrictlyUpperMatrix::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::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::maxNonZeros() noexcept +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + return maxNonZeros( Rows::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::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::resetLower() +{ + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted sparse matrix +inline typename StrictlyUpperMatrix::Iterator + StrictlyUpperMatrix::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::ConstIterator + StrictlyUpperMatrix::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::Iterator + StrictlyUpperMatrix::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::ConstIterator + StrictlyUpperMatrix::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::Iterator + StrictlyUpperMatrix::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::ConstIterator + StrictlyUpperMatrix::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 > 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::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::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::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::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::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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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, ElementType_ > +{ + private: + //**Type definitions**************************************************************************** + //! Reference type of the underlying matrix type. + typedef AddConst_< Reference_ > ReferenceType; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef ElementType_ RepresentedType; //!< Type of the represented matrix element. + typedef AddReference_ 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 list ) const; + + template< typename T > + inline const StrictlyUpperProxy& operator=( initializer_list< initializer_list > 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::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::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& StrictlyUpperProxy::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& + StrictlyUpperProxy::operator=( initializer_list 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& + StrictlyUpperProxy::operator=( initializer_list< initializer_list > 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& StrictlyUpperProxy::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& StrictlyUpperProxy::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& StrictlyUpperProxy::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& StrictlyUpperProxy::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& StrictlyUpperProxy::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::RawReference StrictlyUpperProxy::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::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::operator ConstReference() const noexcept +{ + return static_cast( value_ ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name StrictlyUpperProxy global functions */ +//@{ +template< typename MT > +inline void reset( const StrictlyUpperProxy& proxy ); + +template< typename MT > +inline void clear( const StrictlyUpperProxy& proxy ); + +template< typename MT > +inline bool isDefault( const StrictlyUpperProxy& proxy ); + +template< typename MT > +inline bool isReal( const StrictlyUpperProxy& proxy ); + +template< typename MT > +inline bool isZero( const StrictlyUpperProxy& proxy ); + +template< typename MT > +inline bool isOne( const StrictlyUpperProxy& proxy ); + +template< typename MT > +inline bool isnan( const StrictlyUpperProxy& 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& 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& 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& 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& 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& 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& 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& 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 +#include +#include +#include + + +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 > A; + + // Definition of a resizable column-major dense symmetric matrix based on HybridMatrix + blaze::SymmetricMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense symmetric matrix based on DynamicMatrix + blaze::SymmetricMatrix< blaze::DynamicMatrix > C; + + // Definition of a fixed-size row-major dense symmetric matrix based on CustomMatrix + blaze::SymmetricMatrix< blaze::CustomMatrix > D; + + // Definition of a compressed row-major single precision symmetric matrix + blaze::SymmetricMatrix< blaze::CompressedMatrix > 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 > A; // Both Hermitian and symmetric + HermitianMatrix< DynamicMatrix > B; // Both Hermitian and symmetric + + // The following two matrices will behave differently + SymmetricMatrix< DynamicMatrix< complex > > C; // Only symmetric + HermitianMatrix< DynamicMatrix< complex > > D; // Only Hermitian + + // Block-structured Hermitian matrices are not allowed + SymmetricMatrix< DynamicMatrix< DynamicVector > > E; // Block-structured symmetric matrix + HermitianMatrix< DynamicMatrix< DynamicVector > > 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: +// +// -# \ref symmetricmatrix_square +// -# \ref symmetricmatrix_symmetry +// -# \ref symmetricmatrix_initialization +// +// \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 > 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 > A; + + // Compilation error: the provided matrix type is not a square matrix type + SymmetricMatrix< StaticMatrix > 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 > 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 B( 3.0, 8.0, -2.0, + 8.0, 0.0, -1.0, + -2.0, -1.0, 4.0 ); + + SymmetricMatrix< DynamicMatrix > C( B ); // OK + + // Assignment of a non-symmetric dense matrix + StaticMatrix 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 > 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 > 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 > 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 > A1( 4 ), A2( 4 ); + + // Setup of the 3x2 dynamic matrix + // + // ( 1 2 ) + // B = ( 3 4 ) + // ( 5 6 ) + // + DynamicMatrix 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 A( 5, 5 ); + + // Default initialized, 5x5 row-major symmetric dynamic matrix + SymmetricMatrix< DynamicMatrix > 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 A( 3, 3 ); + CompressedMatrix B( 3, 3 ); + + SymmetricMatrix< DynamicMatrix > C( 3 ); + SymmetricMatrix< CompressedMatrix > D( 3 ); + + SymmetricMatrix< HybridMatrix > E; + SymmetricMatrix< StaticMatrix > 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 > > 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( { { 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 > A; + SymmetricMatrix< CompressedMatrix > B; + DynamicMatrix 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 > A; + CompressedVector x; + DynamicVector 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 > DynamicSymmetric; + + DynamicSymmetric A( 10UL ); + Row 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 > A, C; + DynamicMatrix 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 > 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::value // Storage order of the adapted matrix + , bool DF = IsDenseMatrix::value // Density flag + , bool NF = IsNumericMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public DenseMatrix< SymmetricMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the dense matrix. + typedef TransposeType_ TT; //!< Transpose type of the dense matrix. + typedef ElementType_ ET; //!< Element type of the dense matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef SymmetricMatrix This; //!< Type of this SymmetricMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this SymmetricMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef SymmetricMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef SymmetricMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef Reference_ Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant matrix value. + typedef ConstPointer_ 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::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 + , ConstReference_ + , Reference_ > Reference; + + typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category. + typedef RemoveReference_ 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& 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& 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& 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& 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& 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& 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& 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 Iterator; //!< Iterator over non-constant elements. + typedef MatrixIterator 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::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& m ); + template< typename MT2 > inline SymmetricMatrix( const Matrix& 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, SymmetricMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsComputation, SymmetricMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2 > + inline SymmetricMatrix& operator=( const Matrix& rhs ); + + template< typename MT2 > + inline DisableIf_< IsComputation, SymmetricMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsComputation, SymmetricMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2 > + inline SymmetricMatrix& operator+=( const Matrix& rhs ); + + template< typename MT2 > + inline DisableIf_< IsComputation, SymmetricMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsComputation, SymmetricMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2 > + inline SymmetricMatrix& operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline SymmetricMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, SymmetricMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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 & rhs ); + template< typename MT2 > inline void assign ( const DenseMatrix & rhs ); + template< typename MT2 > inline void assign ( const SparseMatrix& rhs ); + template< typename MT2 > inline void addAssign( const DenseMatrix & rhs ); + template< typename MT2 > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT2 > inline void subAssign( const DenseMatrix & rhs ); + template< typename MT2 > inline void subAssign( const SparseMatrix& 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& 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::value == Columns::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::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::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::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::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::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::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::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::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::SymmetricMatrix( const Matrix& m ) + : matrix_() // The adapted dense matrix +{ + using blaze::resize; + + typedef RemoveAdaptor_ > RT; + typedef If_< IsComputation, RT, const MT2& > Tmp; + + if( IsSymmetric::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::SymmetricMatrix( const Matrix& m ) + : matrix_() // The adapted dense matrix +{ + using blaze::resize; + + typedef RemoveAdaptor_< ResultType_ > RT; + typedef If_< IsComputation, RT, const MT2& > Tmp; + + if( IsSymmetric::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::Reference + SymmetricMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( 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::ConstReference + SymmetricMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( 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::Reference + SymmetricMatrix::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::ConstReference + SymmetricMatrix::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::ConstPointer + SymmetricMatrix::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::ConstPointer + SymmetricMatrix::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::Iterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::Iterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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& + SymmetricMatrix::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& + SymmetricMatrix::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, SymmetricMatrix& > + SymmetricMatrix::operator=( const Matrix& rhs ) +{ + using blaze::resize; + + if( !IsSymmetric::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::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, SymmetricMatrix& > + SymmetricMatrix::operator=( const Matrix& rhs ) +{ + using blaze::resize; + + typedef If_< IsSymmetric, CompositeType_, ResultType_ > Tmp; + + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" ); + } + + Tmp tmp( ~rhs ); + + if( !IsSymmetric::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::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& + SymmetricMatrix::operator=( const Matrix& 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, SymmetricMatrix& > + SymmetricMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsSymmetric::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, SymmetricMatrix& > + SymmetricMatrix::operator+=( const Matrix& rhs ) +{ + typedef If_< IsSymmetric, CompositeType_, ResultType_ > Tmp; + + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" ); + } + + Tmp tmp( ~rhs ); + + if( !IsSymmetric::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& + SymmetricMatrix::operator+=( const Matrix& 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, SymmetricMatrix& > + SymmetricMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsSymmetric::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, SymmetricMatrix& > + SymmetricMatrix::operator-=( const Matrix& rhs ) +{ + typedef If_< IsSymmetric, CompositeType_, ResultType_ > Tmp; + + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" ); + } + + Tmp tmp( ~rhs ); + + if( !IsSymmetric::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& + SymmetricMatrix::operator-=( const Matrix& 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& + SymmetricMatrix::operator*=( const Matrix& rhs ) +{ + using blaze::resize; + + typedef MultTrait_< MT, ResultType_ > 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, SymmetricMatrix >& + SymmetricMatrix::operator*=( Other rhs ) +{ + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted dense matrix +template< typename Other > // Data type of the right-hand side scalar +inline EnableIf_< IsNumeric, SymmetricMatrix >& + SymmetricMatrix::operator/=( Other rhs ) +{ + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted dense matrix +inline size_t SymmetricMatrix::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::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::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::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::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::nonZeros() const +{ + size_t nonzeros( 0UL ); + + if( SO ) + { + for( size_t j=0UL; j // Storage order of the adapted dense matrix +inline size_t SymmetricMatrix::nonZeros( size_t i ) const +{ + size_t nonzeros( 0UL ); + + if( SO ) + { + for( size_t j=0UL; j // Storage order of the adapted dense matrix +inline void SymmetricMatrix::reset() +{ + using blaze::clear; + + if( SO ) { + for( size_t j=0UL; j > > 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::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::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::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::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::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& SymmetricMatrix::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& SymmetricMatrix::ctranspose() +{ + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted dense matrix +template< typename Other > // Data type of the scalar value +inline SymmetricMatrix& + SymmetricMatrix::scale( const Other& scalar ) +{ + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted dense matrix +inline void SymmetricMatrix::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::isIntact() const noexcept +{ + using blaze::isIntact; + + return isIntact( matrix_ ) && + ( IsCustom::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::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::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::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::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::assign( DenseMatrix& 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 // Storage order of the adapted dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline void SymmetricMatrix::assign( const DenseMatrix& 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 // Storage order of the adapted dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void SymmetricMatrix::assign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); + + typedef ConstIterator_ ConstIterator; + + if( SO ) { + for( size_t j=0UL; jindex(),j) = element->value(); + } + } + else { + for( size_t i=0UL; iindex()) = 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::addAssign( const DenseMatrix& 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 // Storage order of the adapted dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void SymmetricMatrix::addAssign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); + + typedef ConstIterator_ ConstIterator; + + if( SO ) { + for( size_t j=0UL; jindex(),j) += element->value(); + } + } + else { + for( size_t i=0UL; iindex()) += 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::subAssign( const DenseMatrix& 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 // Storage order of the adapted dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void SymmetricMatrix::subAssign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( rows() == (~rhs).rows() , "Invalid number of rows" ); + BLAZE_INTERNAL_ASSERT( columns() == (~rhs).columns(), "Invalid number of columns" ); + + typedef ConstIterator_ ConstIterator; + + if( SO ) { + for( size_t j=0UL; jindex(),j) -= element->value(); + } + } + else { + for( size_t i=0UL; iindex()) -= 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public DenseMatrix< SymmetricMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the dense matrix. + typedef TransposeType_ TT; //!< Transpose type of the dense matrix. + typedef ElementType_ ET; //!< Element type of the dense matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef SymmetricMatrix This; //!< Type of this SymmetricMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this SymmetricMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef SymmetricMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef SymmetricMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef SIMDType_ SIMDType; //!< SIMD type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef NumericProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant matrix value. + typedef ConstPointer_ ConstPointer; //!< Pointer to a constant matrix value. + typedef ConstIterator_ 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::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_ ValueType; //!< Type of the underlying elements. + typedef NumericProxy PointerType; //!< Pointer return type. + typedef NumericProxy 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 > 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& m ); + template< typename MT2 > inline SymmetricMatrix( const Matrix& 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 > 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, SymmetricMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsComputation, SymmetricMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2 > + inline SymmetricMatrix& operator=( const Matrix& rhs ); + + template< typename MT2 > + inline DisableIf_< IsComputation, SymmetricMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsComputation, SymmetricMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2 > + inline SymmetricMatrix& operator+=( const Matrix& rhs ); + + template< typename MT2 > + inline DisableIf_< IsComputation, SymmetricMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsComputation, SymmetricMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2 > + inline SymmetricMatrix& operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline SymmetricMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, SymmetricMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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::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& m ); + + template< typename MT2, bool SO2 > + friend void invert2x2( SymmetricMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invert3x3( SymmetricMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invert4x4( SymmetricMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invert5x5( SymmetricMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invert6x6( SymmetricMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invertByLU( SymmetricMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invertByLDLT( SymmetricMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invertByLDLH( SymmetricMatrix& m ); + + template< typename MT2, bool SO2 > + friend void invertByLLH( SymmetricMatrix& 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::value == Columns::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::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::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 > 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::SymmetricMatrix( initializer_list< initializer_list > 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 > 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::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 > 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::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::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::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::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::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::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::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::SymmetricMatrix( const Matrix& m ) + : matrix_( ~m ) // The adapted dense matrix +{ + if( !IsSymmetric::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::SymmetricMatrix( const Matrix& m ) + : matrix_( trans( ~m ) ) // The adapted dense matrix +{ + if( !IsSymmetric::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::Reference + SymmetricMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename SymmetricMatrix::ConstReference + SymmetricMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename SymmetricMatrix::Reference + SymmetricMatrix::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::ConstReference + SymmetricMatrix::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::ConstPointer + SymmetricMatrix::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::ConstPointer + SymmetricMatrix::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::Iterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::Iterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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 > 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& + SymmetricMatrix::operator=( initializer_list< initializer_list > 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 > 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& + SymmetricMatrix::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& + SymmetricMatrix::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& + SymmetricMatrix::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, SymmetricMatrix& > + SymmetricMatrix::operator=( const Matrix& rhs ) +{ + if( !IsSymmetric::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, SymmetricMatrix& > + SymmetricMatrix::operator=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" ); + } + + if( IsSymmetric::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& + SymmetricMatrix::operator=( const Matrix& 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, SymmetricMatrix& > + SymmetricMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsSymmetric::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, SymmetricMatrix& > + SymmetricMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" ); + } + + if( IsSymmetric::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ 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& + SymmetricMatrix::operator+=( const Matrix& 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, SymmetricMatrix& > + SymmetricMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsSymmetric::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, SymmetricMatrix& > + SymmetricMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" ); + } + + if( IsSymmetric::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ 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& + SymmetricMatrix::operator-=( const Matrix& 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& + SymmetricMatrix::operator*=( const Matrix& 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, SymmetricMatrix >& + SymmetricMatrix::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, SymmetricMatrix >& + SymmetricMatrix::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::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::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::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::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::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::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::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::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 > 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::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::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::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::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::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& SymmetricMatrix::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& SymmetricMatrix::ctranspose() +{ + if( !IsBuiltin::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& + SymmetricMatrix::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::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::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::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::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::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::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::SIMDType + SymmetricMatrix::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::SIMDType + SymmetricMatrix::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::SIMDType + SymmetricMatrix::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::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 // Storage order of the adapted dense matrix +inline void + SymmetricMatrix::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 // Storage order of the adapted dense matrix +inline void + SymmetricMatrix::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 // Storage order of the adapted dense matrix +inline void + SymmetricMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 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, ValueType_< ElementType_ > > +{ + private: + //**Enumerations******************************************************************************** + //! Compile time flag indicating whether the given matrix type is a row-major matrix. + enum : bool { rmm = IsRowMajorMatrix::value }; + //********************************************************************************************** + + //**Type definitions**************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef ElementType_ ET; //!< Element type of the adapted matrix. + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef ValueType_ RepresentedType; //!< Type of the represented matrix element. + typedef Reference_ 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 list ); + + template< typename T > + inline NonNumericProxy& operator=( initializer_list< initializer_list > 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::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_ 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::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::~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& NonNumericProxy::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& NonNumericProxy::operator=( initializer_list 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& NonNumericProxy::operator=( initializer_list< initializer_list > 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& NonNumericProxy::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& NonNumericProxy::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& NonNumericProxy::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& NonNumericProxy::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& NonNumericProxy::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::RawReference NonNumericProxy::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::operator RawReference() const noexcept +{ + return get(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name NonNumericProxy global functions */ +//@{ +template< typename MT > +inline void reset( const NonNumericProxy& proxy ); + +template< typename MT > +inline void clear( const NonNumericProxy& proxy ); + +template< typename MT > +inline bool isDefault( const NonNumericProxy& proxy ); + +template< typename MT > +inline bool isReal( const NonNumericProxy& proxy ); + +template< typename MT > +inline bool isZero( const NonNumericProxy& proxy ); + +template< typename MT > +inline bool isOne( const NonNumericProxy& proxy ); + +template< typename MT > +inline bool isnan( const NonNumericProxy& 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& 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& 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& 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& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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 > +{ + 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_ RepresentedType; //!< Type of the represented matrix element. + typedef Reference_ Reference; //!< Reference to the represented element. + typedef ConstReference_ 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 + , ComplexType + , BuiltinType >::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::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::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& NumericProxy::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& NumericProxy::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& NumericProxy::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& NumericProxy::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& NumericProxy::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& NumericProxy::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::Pointer NumericProxy::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::ConstPointer NumericProxy::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::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::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::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::ConstReference NumericProxy::get() const noexcept +{ + return const_cast( 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::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::ValueType NumericProxy::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::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::ValueType NumericProxy::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::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& proxy ); + +template< typename MT > +inline void clear( const NumericProxy& proxy ); + +template< typename MT > +inline void invert( const NumericProxy& proxy ); + +template< typename MT > +inline bool isDefault( const NumericProxy& proxy ); + +template< typename MT > +inline bool isReal( const NumericProxy& proxy ); + +template< typename MT > +inline bool isZero( const NumericProxy& proxy ); + +template< typename MT > +inline bool isOne( const NumericProxy& proxy ); + +template< typename MT > +inline bool isnan( const NumericProxy& 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& 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& 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& 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& 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& 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& 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& 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& 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 +#include +#include +#include +#include + + +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 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::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::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::Reference SharedValue::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::ConstReference SharedValue::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::Pointer SharedValue::base() const noexcept +{ + return value_.get(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name SharedValue operators */ +//@{ +template< typename T1, typename T2 > +inline bool operator==( const SharedValue& lhs, const SharedValue& rhs ); + +template< typename T1, typename T2 > +inline bool operator!=( const SharedValue& lhs, const SharedValue& 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& lhs, const SharedValue& 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& lhs, const SharedValue& rhs ) +{ + return ( lhs.base() != rhs.base() ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name SharedValue global functions */ +//@{ +template< typename Type > +inline bool isDefault( const SharedValue& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public SparseMatrix< SymmetricMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the sparse matrix. + typedef TransposeType_ TT; //!< Transpose type of the sparse matrix. + typedef ElementType_ ET; //!< Element type of the sparse matrix. + + //! Rebound matrix type for shared values. + typedef typename MT::template Rebind< SharedValue >::Other MatrixType; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef SymmetricMatrix This; //!< Type of this SymmetricMatrix instance. + typedef SparseMatrix BaseType; //!< Base type of this SymmetricMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef SymmetricMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef SymmetricMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef NonNumericProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ 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::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& 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_ > + , Iterator_ + > Iterator; + + //! Iterator over constant elements. + typedef SharedIterator< const SharedElement< ConstIterator_ > + , ConstIterator_ + > 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& nonzeros ); + + inline SymmetricMatrix( const SymmetricMatrix& m ); + inline SymmetricMatrix( SymmetricMatrix&& m ) noexcept; + + template< typename MT2 > inline SymmetricMatrix( const Matrix& m ); + template< typename MT2 > inline SymmetricMatrix( const Matrix& 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, SymmetricMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsComputation, SymmetricMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2 > + inline SymmetricMatrix& operator=( const Matrix& rhs ); + + template< typename MT2 > + inline SymmetricMatrix& operator+=( const Matrix& rhs ); + + template< typename MT2 > + inline SymmetricMatrix& operator+=( const Matrix& rhs ); + + template< typename MT2 > + inline SymmetricMatrix& operator-=( const Matrix& rhs ); + + template< typename MT2 > + inline SymmetricMatrix& operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline SymmetricMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, SymmetricMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& rhs ); + template< typename MT2 > void assign( const DenseMatrix& rhs ); + template< typename MT2 > void assign( SparseMatrix& rhs ); + template< typename MT2 > void assign( const SparseMatrix& 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& 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::value == Columns::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::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::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::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::SymmetricMatrix( size_t n, const std::vector& 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::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::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::SymmetricMatrix( const Matrix& m ) + : matrix_() // The adapted sparse matrix +{ + using blaze::resize; + + typedef RemoveAdaptor_< ResultType_ > RT; + typedef If_< IsComputation, RT, const MT2& > Tmp; + + Tmp tmp( ~m ); + + if( !IsSymmetric::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::SymmetricMatrix( const Matrix& m ) + : matrix_() // The adapted sparse matrix +{ + using blaze::resize; + + typedef RemoveAdaptor_< ResultType_ > RT; + typedef If_< IsComputation, RT, const MT2& > Tmp; + + Tmp tmp( ~m ); + + if( !IsSymmetric::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::Reference + SymmetricMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename SymmetricMatrix::ConstReference + SymmetricMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename SymmetricMatrix::Reference + SymmetricMatrix::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::ConstReference + SymmetricMatrix::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::Iterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::Iterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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& + SymmetricMatrix::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& + SymmetricMatrix::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, SymmetricMatrix& > + SymmetricMatrix::operator=( const Matrix& rhs ) +{ + using blaze::resize; + + if( !IsSymmetric::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, SymmetricMatrix& > + SymmetricMatrix::operator=( const Matrix& rhs ) +{ + using blaze::resize; + + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" ); + } + + const ResultType_ tmp( ~rhs ); + + if( !IsSymmetric::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& + SymmetricMatrix::operator=( const Matrix& 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& + SymmetricMatrix::operator+=( const Matrix& rhs ) +{ + using blaze::resize; + + typedef AddTrait_< MT, ResultType_ > Tmp; + + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" ); + } + + Tmp tmp( (*this) + ~rhs ); + + if( !IsSymmetric::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& + SymmetricMatrix::operator+=( const Matrix& 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& + SymmetricMatrix::operator-=( const Matrix& rhs ) +{ + using blaze::resize; + + typedef SubTrait_< MT, ResultType_ > Tmp; + + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" ); + } + + Tmp tmp( (*this) - ~rhs ); + + if( !IsSymmetric::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& + SymmetricMatrix::operator-=( const Matrix& 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& + SymmetricMatrix::operator*=( const Matrix& rhs ) +{ + using blaze::resize; + + typedef MultTrait_< MT, ResultType_ > Tmp; + + if( matrix_.rows() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" ); + } + + Tmp tmp( (*this) * ~rhs ); + + if( !IsSymmetric::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, SymmetricMatrix >& + SymmetricMatrix::operator*=( Other rhs ) +{ + for( size_t i=0UL; i last( matrix_.upperBound(i,i) ); + for( Iterator_ 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, SymmetricMatrix >& + SymmetricMatrix::operator/=( Other rhs ) +{ + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + for( size_t i=0UL; i last( matrix_.upperBound(i,i) ); + for( Iterator_ 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::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::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::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::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::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::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::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 > > 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::reset( size_t i ) +{ + for( Iterator_ it=matrix_.begin(i); it!=matrix_.end(i); ++it ) + { + const size_t j( it->index() ); + + if( i == j ) + continue; + + if( SO ) { + const Iterator_ pos( matrix_.find( i, j ) ); + BLAZE_INTERNAL_ASSERT( pos != matrix_.end( j ), "Missing element detected" ); + matrix_.erase( j, pos ); + } + else { + const Iterator_ 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::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::Iterator + SymmetricMatrix::set( size_t i, size_t j, const ElementType& value ) +{ + SharedValue 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::Iterator + SymmetricMatrix::insert( size_t i, size_t j, const ElementType& value ) +{ + SharedValue 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::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::Iterator + SymmetricMatrix::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::Iterator + SymmetricMatrix::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::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::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::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::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::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& SymmetricMatrix::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& SymmetricMatrix::ctranspose() +{ + for( size_t i=0UL; i last( matrix_.upperBound(i,i) ); + for( Iterator_ 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& + SymmetricMatrix::scale( const Other& scalar ) +{ + for( size_t i=0UL; i last( matrix_.upperBound(i,i) ); + for( Iterator_ 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& + SymmetricMatrix::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::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::Iterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::Iterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::Iterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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 > 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::append( size_t i, size_t j, const ElementType& value, bool check ) +{ + SharedValue 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::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::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::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::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::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::assign( DenseMatrix& 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 nonzeros( rows(), 0UL ); + size_t sum( 0UL ); + + for( size_t i=0UL; i 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::assign( const DenseMatrix& 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 nonzeros( rows(), 0UL ); + size_t sum( 0UL ); + + for( size_t i=0UL; i 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::assign( SparseMatrix& 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 nonzeros( rows(), 0UL ); + size_t sum( 0UL ); + + for( size_t i=0UL; i it=(~rhs).lowerBound(i,i); it!=(~rhs).end(i); ++it ) { + if( !isDefault( it->value() ) ) { + SharedValue 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::assign( const SparseMatrix& 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 nonzeros( rows(), 0UL ); + size_t sum( 0UL ); + + for( size_t i=0UL; i it=(~rhs).lowerBound(i,i); it!=(~rhs).end(i); ++it ) { + if( !isDefault( it->value() ) ) { + const SharedValue 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public SparseMatrix< SymmetricMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the sparse matrix. + typedef TransposeType_ TT; //!< Transpose type of the sparse matrix. + typedef ElementType_ ET; //!< Element type of the sparse matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef SymmetricMatrix This; //!< Type of this SymmetricMatrix instance. + typedef SparseMatrix BaseType; //!< Base type of this SymmetricMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef SymmetricMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef SymmetricMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef NumericProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef ConstIterator_ 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::Other > Other; + }; + //********************************************************************************************** + + //**Iterator class definition******************************************************************* + /*!\brief Iterator over the elements of the sparse symmetric matrix. + */ + class Iterator + { + public: + //**Type definitions************************************************************************* + typedef Iterator_ IteratorType; //!< Type of the underlying sparse matrix iterators. + + typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category. + typedef SymmetricElement 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& nonzeros ); + + inline SymmetricMatrix( const SymmetricMatrix& m ); + inline SymmetricMatrix( SymmetricMatrix&& m ) noexcept; + + template< typename MT2 > inline SymmetricMatrix( const Matrix& m ); + template< typename MT2 > inline SymmetricMatrix( const Matrix& 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, SymmetricMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsComputation, SymmetricMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2 > + inline SymmetricMatrix& operator=( const Matrix& rhs ); + + template< typename MT2 > + inline DisableIf_< IsComputation, SymmetricMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsComputation, SymmetricMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2 > + inline SymmetricMatrix& operator+=( const Matrix& rhs ); + + template< typename MT2 > + inline DisableIf_< IsComputation, SymmetricMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2 > + inline EnableIf_< IsComputation, SymmetricMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2 > + inline SymmetricMatrix& operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline SymmetricMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, SymmetricMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& 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::value == Columns::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::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::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::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::SymmetricMatrix( size_t n, const std::vector& 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::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::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::SymmetricMatrix( const Matrix& m ) + : matrix_( ~m ) // The adapted sparse matrix +{ + if( !IsSymmetric::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::SymmetricMatrix( const Matrix& m ) + : matrix_( trans( ~m ) ) // The adapted sparse matrix +{ + if( !IsSymmetric::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::Reference + SymmetricMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename SymmetricMatrix::ConstReference + SymmetricMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename SymmetricMatrix::Reference + SymmetricMatrix::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::ConstReference + SymmetricMatrix::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::Iterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::Iterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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& + SymmetricMatrix::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& + SymmetricMatrix::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, SymmetricMatrix& > + SymmetricMatrix::operator=( const Matrix& rhs ) +{ + if( !IsSymmetric::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, SymmetricMatrix& > + SymmetricMatrix::operator=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" ); + } + + if( IsSymmetric::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& + SymmetricMatrix::operator=( const Matrix& 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, SymmetricMatrix& > + SymmetricMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsSymmetric::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, SymmetricMatrix& > + SymmetricMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" ); + } + + if( IsSymmetric::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ 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& + SymmetricMatrix::operator+=( const Matrix& 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, SymmetricMatrix& > + SymmetricMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsSymmetric::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, SymmetricMatrix& > + SymmetricMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to symmetric matrix" ); + } + + if( IsSymmetric::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ 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& + SymmetricMatrix::operator-=( const Matrix& 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& + SymmetricMatrix::operator*=( const Matrix& 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, SymmetricMatrix >& + SymmetricMatrix::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, SymmetricMatrix >& + SymmetricMatrix::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::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::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::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::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::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::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::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 > 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::reset( size_t i ) +{ + for( Iterator_ it=matrix_.begin(i); it!=matrix_.end(i); ++it ) + { + const size_t j( it->index() ); + + if( i == j ) + continue; + + if( SO ) { + const Iterator_ pos( matrix_.find( i, j ) ); + BLAZE_INTERNAL_ASSERT( pos != matrix_.end( j ), "Missing element detected" ); + matrix_.erase( j, pos ); + } + else { + const Iterator_ 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::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::Iterator + SymmetricMatrix::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::Iterator + SymmetricMatrix::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::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::Iterator + SymmetricMatrix::erase( size_t i, Iterator pos ) +{ + const Iterator_ 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::Iterator + SymmetricMatrix::erase( size_t i, Iterator first, Iterator last ) +{ + for( Iterator_ 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::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::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::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::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::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& SymmetricMatrix::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& SymmetricMatrix::ctranspose() +{ + if( !IsBuiltin::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& + SymmetricMatrix::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& + SymmetricMatrix::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::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::Iterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::Iterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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::Iterator + SymmetricMatrix::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::ConstIterator + SymmetricMatrix::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 > 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::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::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::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::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::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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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_ ElementType; //!< Type of the represented matrix element. + typedef Iterator_ IteratorType; //!< Type of the underlying sparse matrix iterators. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef SymmetricValue ValueType; //!< The value type of the value-index-pair. + typedef size_t IndexType; //!< The index type of the value-index-pair. + typedef SymmetricValue Reference; //!< Reference return type. + typedef const SymmetricValue 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::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& SymmetricElement::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& SymmetricElement::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& SymmetricElement::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& SymmetricElement::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& SymmetricElement::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::Pointer SymmetricElement::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::Reference SymmetricElement::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::IndexType SymmetricElement::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::sync() +{ + if( pos_->index() == index_ || isDefault( pos_->value() ) ) + return; + + const size_t row ( ( IsRowMajorMatrix::value )?( pos_->index() ):( index_ ) ); + const size_t column( ( IsRowMajorMatrix::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::isSynced() const +{ + const size_t row ( ( IsRowMajorMatrix::value )?( pos_->index() ):( index_ ) ); + const size_t column( ( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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 > +{ + 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_ RepresentedType; //!< Type of the represented matrix element. + + //! Value type of the represented complex element. + typedef typename If_< IsComplex + , ComplexType + , BuiltinType >::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::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& SymmetricValue::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& SymmetricValue::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& SymmetricValue::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& SymmetricValue::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& SymmetricValue::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& SymmetricValue::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::reset() const +{ + using blaze::reset; + + reset( pos_->value() ); + + if( pos_->index() != index_ ) + { + const size_t row ( ( IsRowMajorMatrix::value )?( pos_->index() ):( index_ ) ); + const size_t column( ( IsRowMajorMatrix::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::clear() const +{ + using blaze::clear; + + clear( pos_->value() ); + + if( pos_->index() != index_ ) + { + const size_t row ( ( IsRowMajorMatrix::value )?( pos_->index() ):( index_ ) ); + const size_t column( ( IsRowMajorMatrix::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::invert() const +{ + using blaze::invert; + + invert( pos_->value() ); + + if( pos_->index() != index_ ) + { + const size_t row ( ( IsRowMajorMatrix::value )?( pos_->index() ):( index_ ) ); + const size_t column( ( IsRowMajorMatrix::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::RepresentedType SymmetricValue::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::sync() const +{ + if( pos_->index() == index_ || isDefault( pos_->value() ) ) + return; + + const size_t row ( ( IsRowMajorMatrix::value )?( pos_->index() ):( index_ ) ); + const size_t column( ( IsRowMajorMatrix::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::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::ValueType SymmetricValue::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::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::ValueType SymmetricValue::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::imag( ValueType value ) const +{ + pos_->value().imag( value ); + sync(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name SymmetricValue global functions */ +//@{ +template< typename MT > +inline void reset( const SymmetricValue& value ); + +template< typename MT > +inline void clear( const SymmetricValue& value ); + +template< typename MT > +inline void invert( const SymmetricValue& value ); + +template< typename MT > +inline bool isDefault( const SymmetricValue& value ); + +template< typename MT > +inline bool isReal( const SymmetricValue& value ); + +template< typename MT > +inline bool isZero( const SymmetricValue& value ); + +template< typename MT > +inline bool isOne( const SymmetricValue& value ); + +template< typename MT > +inline bool isnan( const SymmetricValue& 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& 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& 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& 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& 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& 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& 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& 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& 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 +#include + + +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 > A; + + // Definition of a resizable column-major dense unilower matrix based on HybridMatrix + blaze::UniLowerMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense unilower matrix based on DynamicMatrix + blaze::UniLowerMatrix< blaze::DynamicMatrix > C; + + // Definition of a fixed-size row-major dense unilower matrix based on CustomMatrix + blaze::UniLowerMatrix< blaze::CustomMatrix > D; + + // Definition of a compressed row-major single precision unilower matrix + blaze::UniLowerMatrix< blaze::CompressedMatrix > 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: +// +// -# \ref unilowermatrix_square +// -# \ref unilowermatrix_unilower +// -# \ref unilowermatrix_initialization +// -# \ref unilowermatrix_storage +// -# \ref unilowermatrix_scaling + +// +// \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 > 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 > A; + + // Compilation error: the provided matrix type is not a square matrix type + UniLowerMatrix< StaticMatrix > 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 > A( 3UL ); + + // Creating a default initialized sparse unilower matrix of size 3x3 + // + // ( 1 0 0 ) + // B = ( 0 1 0 ) + // ( 0 0 1 ) + UniLowerMatrix< CompressedMatrix > 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 > 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 B( 1.0, 0.0, 0.0, + 8.0, 1.0, 0.0, + -2.0, -1.0, 1.0 ); + + UniLowerMatrix< DynamicMatrix > C( B ); // OK + + // Assignment of a non-unilower dense matrix + StaticMatrix 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 > 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 > 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 > A1( 4 ), A2( 4 ); + + // Setup of a 4-dimensional vector + // + // v = ( 1 2 3 0 ) + // + DynamicVector 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 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 A( 5, 5 ); + + // 5x5 row-major unilower dynamic matrix with default initialized upper matrix + UniLowerMatrix< DynamicMatrix > 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 > 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 A( 3, 3 ); + CompressedMatrix B( 3, 3 ); + + UniLowerMatrix< DynamicMatrix > C( 3 ); + UniLowerMatrix< CompressedMatrix > D( 3 ); + + UniLowerMatrix< HybridMatrix > E; + UniLowerMatrix< StaticMatrix > F; + + DynamicMatrix G( 3, 3 ); // Initialized as strictly lower matrix + CompressedMatrix 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 > A; + UniLowerMatrix< DynamicMatrix > B; + DynamicMatrix 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 > A; + DynamicVector 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 > A, C; + DynamicMatrix 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 > 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::value // Storage order of the adapted matrix + , bool DF = IsDenseMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public DenseMatrix< UniLowerMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the dense matrix. + typedef TransposeType_ TT; //!< Transpose type of the dense matrix. + typedef ElementType_ ET; //!< Element type of the dense matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef UniLowerMatrix This; //!< Type of this UniLowerMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this UniLowerMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef UniLowerMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef UniUpperMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef SIMDType_ SIMDType; //!< SIMD type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef UniLowerProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant matrix value. + typedef ConstPointer_ ConstPointer; //!< Pointer to a constant matrix value. + typedef ConstIterator_ 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::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_ ValueType; //!< Type of the underlying elements. + typedef UniLowerProxy PointerType; //!< Pointer return type. + typedef UniLowerProxy 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 > 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 > 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, UniLowerMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UniLowerMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, UniLowerMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UniLowerMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, UniLowerMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UniLowerMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline UniLowerMatrix& operator*=( const Matrix& 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& 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& 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::value == Columns::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::UniLowerMatrix() + : matrix_() // The adapted dense matrix +{ + for( size_t i=0UL; i::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::UniLowerMatrix( const A1& a1 ) + : matrix_( construct( a1, typename IsResizable::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::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 > 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::UniLowerMatrix( initializer_list< initializer_list > 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 > 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::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 > 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::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::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::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::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::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::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::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::Reference + UniLowerMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename UniLowerMatrix::ConstReference + UniLowerMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename UniLowerMatrix::Reference + UniLowerMatrix::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::ConstReference + UniLowerMatrix::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::ConstPointer + UniLowerMatrix::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::ConstPointer + UniLowerMatrix::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::Iterator + UniLowerMatrix::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::ConstIterator + UniLowerMatrix::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::ConstIterator + UniLowerMatrix::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::Iterator + UniLowerMatrix::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::ConstIterator + UniLowerMatrix::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::ConstIterator + UniLowerMatrix::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& + UniLowerMatrix::operator=( const ElementType& rhs ) +{ + if( SO ) { + for( size_t j=0UL; j > 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& + UniLowerMatrix::operator=( initializer_list< initializer_list > 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 > 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& + UniLowerMatrix::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& + UniLowerMatrix::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& + UniLowerMatrix::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, UniLowerMatrix& > + UniLowerMatrix::operator=( const Matrix& rhs ) +{ + if( IsStrictlyTriangular::value || ( !IsUniLower::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, UniLowerMatrix& > + UniLowerMatrix::operator=( const Matrix& rhs ) +{ + if( IsStrictlyTriangular::value || ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" ); + } + + if( IsUniLower::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, UniLowerMatrix& > + UniLowerMatrix::operator+=( const Matrix& rhs ) +{ + if( IsUpper::value || IsUniTriangular::value || + ( !IsStrictlyLower::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, UniLowerMatrix& > + UniLowerMatrix::operator+=( const Matrix& rhs ) +{ + if( IsUpper::value || IsUniTriangular::value || + ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" ); + } + + if( IsStrictlyLower::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ 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, UniLowerMatrix& > + UniLowerMatrix::operator-=( const Matrix& rhs ) +{ + if( IsUpper::value || IsUniTriangular::value || + ( !IsStrictlyLower::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, UniLowerMatrix& > + UniLowerMatrix::operator-=( const Matrix& rhs ) +{ + if( IsUpper::value || IsUniTriangular::value || + ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" ); + } + + if( IsStrictlyLower::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ 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& + UniLowerMatrix::operator*=( const Matrix& 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::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::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::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::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::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::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::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::reset() +{ + using blaze::clear; + + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted dense matrix +inline void UniLowerMatrix::reset( size_t i ) +{ + using blaze::clear; + + if( SO ) { + for( size_t j=i+1UL; j // Storage order of the adapted dense matrix +inline void UniLowerMatrix::clear() +{ + using blaze::clear; + + if( IsResizable::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::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 // Storage order of the adapted dense matrix +inline void UniLowerMatrix::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::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::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::maxNonZeros() noexcept +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + return maxNonZeros( Rows::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::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::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::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::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::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::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::SIMDType + UniLowerMatrix::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::SIMDType + UniLowerMatrix::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::SIMDType + UniLowerMatrix::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::construct( size_t n, TrueType ) +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + MT tmp( n, n, ElementType() ); + + for( size_t i=0UL; i // Storage order of the adapted dense matrix +inline const MT UniLowerMatrix::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 // 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::construct( const Matrix& m, T ) +{ + const MT tmp( ~m ); + + if( IsStrictlyTriangular::value || ( !IsUniLower::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public SparseMatrix< UniLowerMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the sparse matrix. + typedef TransposeType_ TT; //!< Transpose type of the sparse matrix. + typedef ElementType_ ET; //!< Element type of the sparse matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef UniLowerMatrix This; //!< Type of this UniLowerMatrix instance. + typedef SparseMatrix BaseType; //!< Base type of this UniLowerMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef UniLowerMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef UniUpperMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef UniLowerProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef ConstIterator_ 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::Other > Other; + }; + //********************************************************************************************** + + //**Iterator class definition******************************************************************* + /*!\brief Iterator over the elements of the lower unitriangular matrix. + */ + class Iterator + { + public: + //**Type definitions************************************************************************* + typedef Iterator_ IteratorType; //!< Type of the underlying sparse matrix iterators. + + typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category. + typedef UniLowerElement 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& nonzeros ); + + inline UniLowerMatrix( const UniLowerMatrix& m ); + inline UniLowerMatrix( UniLowerMatrix&& m ) noexcept; + + template< typename MT2, bool SO2 > + inline UniLowerMatrix( const Matrix& 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, UniLowerMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UniLowerMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, UniLowerMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UniLowerMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, UniLowerMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UniLowerMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline UniLowerMatrix& operator*=( const Matrix& 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& 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::value == Columns::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::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::UniLowerMatrix( size_t n ) + : matrix_( n, n, n ) // The adapted sparse matrix +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + for( size_t i=0UL; i // Storage order of the adapted sparse matrix +inline UniLowerMatrix::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 // Storage order of the adapted sparse matrix +inline UniLowerMatrix::UniLowerMatrix( size_t n, const std::vector& nonzeros ) + : matrix_( n, n, nonzeros ) // The adapted sparse matrix +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + for( size_t i=0UL; i // Storage order of the adapted sparse matrix +inline UniLowerMatrix::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::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::UniLowerMatrix( const Matrix& m ) + : matrix_( ~m ) // The adapted sparse matrix +{ + if( !IsUniLower::value && !isUniLower( matrix_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of unilower matrix" ); + } + + if( !IsUniLower::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::Reference + UniLowerMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename UniLowerMatrix::ConstReference + UniLowerMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename UniLowerMatrix::Reference + UniLowerMatrix::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::ConstReference + UniLowerMatrix::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::Iterator + UniLowerMatrix::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::ConstIterator + UniLowerMatrix::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::ConstIterator + UniLowerMatrix::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::Iterator + UniLowerMatrix::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::ConstIterator + UniLowerMatrix::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::ConstIterator + UniLowerMatrix::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& + UniLowerMatrix::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& + UniLowerMatrix::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, UniLowerMatrix& > + UniLowerMatrix::operator=( const Matrix& rhs ) +{ + if( IsStrictlyTriangular::value || ( !IsUniLower::value && !isUniLower( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" ); + } + + matrix_ = ~rhs; + + if( !IsUniLower::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, UniLowerMatrix& > + UniLowerMatrix::operator=( const Matrix& rhs ) +{ + if( IsStrictlyTriangular::value || ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" ); + } + + if( IsUniLower::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::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, UniLowerMatrix& > + UniLowerMatrix::operator+=( const Matrix& rhs ) +{ + if( IsUpper::value || IsUniTriangular::value || + ( !IsStrictlyLower::value && !isStrictlyLower( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" ); + } + + matrix_ += ~rhs; + + if( !IsStrictlyLower::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, UniLowerMatrix& > + UniLowerMatrix::operator+=( const Matrix& rhs ) +{ + if( IsUpper::value || IsUniTriangular::value || + ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" ); + } + + if( IsStrictlyLower::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ tmp( ~rhs ); + + if( !isStrictlyLower( tmp ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" ); + } + + matrix_ += tmp; + } + + if( !IsStrictlyLower::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, UniLowerMatrix& > + UniLowerMatrix::operator-=( const Matrix& rhs ) +{ + if( IsUpper::value || IsUniTriangular::value || + ( !IsStrictlyLower::value && !isStrictlyLower( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" ); + } + + matrix_ -= ~rhs; + + if( !IsStrictlyLower::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, UniLowerMatrix& > + UniLowerMatrix::operator-=( const Matrix& rhs ) +{ + if( IsUpper::value || IsUniTriangular::value || + ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" ); + } + + if( IsStrictlyLower::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ tmp( ~rhs ); + + if( !isStrictlyLower( tmp ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to unilower matrix" ); + } + + matrix_ -= tmp; + } + + if( !IsStrictlyLower::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& + UniLowerMatrix::operator*=( const Matrix& 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::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::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::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::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::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::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::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::reset() +{ + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted sparse matrix +inline void UniLowerMatrix::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::clear() +{ + using blaze::clear; + + if( IsResizable::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::Iterator + UniLowerMatrix::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::Iterator + UniLowerMatrix::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::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::Iterator + UniLowerMatrix::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::Iterator + UniLowerMatrix::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::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 // Storage order of the adapted sparse matrix +inline void UniLowerMatrix::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::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::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::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::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::maxNonZeros() noexcept +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + return maxNonZeros( Rows::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::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::resetUpper() +{ + if( SO ) { + for( size_t j=1UL; j // Storage order of the adapted sparse matrix +inline typename UniLowerMatrix::Iterator + UniLowerMatrix::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::ConstIterator + UniLowerMatrix::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::Iterator + UniLowerMatrix::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::ConstIterator + UniLowerMatrix::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::Iterator + UniLowerMatrix::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::ConstIterator + UniLowerMatrix::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 > 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::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::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::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::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::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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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_ ElementType; //!< Type of the represented matrix element. + typedef Iterator_ IteratorType; //!< Type of the underlying sparse matrix iterators. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef UniLowerValue ValueType; //!< The value type of the value-index-pair. + typedef size_t IndexType; //!< The index type of the value-index-pair. + typedef UniLowerValue Reference; //!< Reference return type. + typedef const UniLowerValue 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::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& UniLowerElement::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& UniLowerElement::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& UniLowerElement::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& UniLowerElement::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& UniLowerElement::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::Pointer UniLowerElement::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::Reference UniLowerElement::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::IndexType UniLowerElement::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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 > +{ + 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_ RepresentedType; + + //! Value type of the represented complex element. + typedef typename If_< IsComplex + , ComplexType + , BuiltinType >::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::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::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& UniLowerProxy::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& UniLowerProxy::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& UniLowerProxy::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& UniLowerProxy::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& UniLowerProxy::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& UniLowerProxy::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::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::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::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::RepresentedType UniLowerProxy::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::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::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::ValueType UniLowerProxy::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::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::ValueType UniLowerProxy::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::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& proxy ); + +template< typename MT > +inline void clear( const UniLowerProxy& proxy ); + +template< typename MT > +inline void invert( const UniLowerProxy& proxy ); + +template< typename MT > +inline bool isDefault( const UniLowerProxy& proxy ); + +template< typename MT > +inline bool isReal( const UniLowerProxy& proxy ); + +template< typename MT > +inline bool isZero( const UniLowerProxy& proxy ); + +template< typename MT > +inline bool isOne( const UniLowerProxy& proxy ); + +template< typename MT > +inline bool isnan( const UniLowerProxy& 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& 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& 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& 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& 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& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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 > +{ + 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_ RepresentedType; //!< Type of the represented matrix element. + + //! Value type of the represented complex element. + typedef typename If_< IsComplex + , ComplexType + , BuiltinType >::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::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& UniLowerValue::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& UniLowerValue::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& UniLowerValue::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& UniLowerValue::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& UniLowerValue::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& UniLowerValue::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::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::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::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::RepresentedType UniLowerValue::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::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::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::ValueType UniLowerValue::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::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::ValueType UniLowerValue::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::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& value ); + +template< typename MT > +inline void clear( const UniLowerValue& value ); + +template< typename MT > +inline void invert( const UniLowerValue& value ); + +template< typename MT > +inline bool isDefault( const UniLowerValue& value ); + +template< typename MT > +inline bool isReal( const UniLowerValue& value ); + +template< typename MT > +inline bool isZero( const UniLowerValue& value ); + +template< typename MT > +inline bool isOne( const UniLowerValue& value ); + +template< typename MT > +inline bool isnan( const UniLowerValue& 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& 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& 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& 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& 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& 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& 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& 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& 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 +#include + + +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 > A; + + // Definition of a resizable column-major dense uniupper matrix based on HybridMatrix + blaze::UniUpperMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense uniupper matrix based on DynamicMatrix + blaze::UniUpperMatrix< blaze::DynamicMatrix > C; + + // Definition of a fixed-size row-major dense uniupper matrix based on CustomMatrix + blaze::UniUpperMatrix< blaze::CustomMatrix > D; + + // Definition of a compressed row-major single precision uniupper matrix + blaze::UniUpperMatrix< blaze::CompressedMatrix > 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: +// +// -# \ref uniuppermatrix_square +// -# \ref uniuppermatrix_uniupper +// -# \ref uniuppermatrix_initialization +// -# \ref uniuppermatrix_storage +// -# \ref uniuppermatrix_scaling +// +// \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 > 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 > A; + + // Compilation error: the provided matrix type is not a square matrix type + UniUpperMatrix< StaticMatrix > 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 > A( 3UL ); + + // Creating a default initialized sparse uniupper matrix of size 3x3 + // + // ( 1 0 0 ) + // B = ( 0 1 0 ) + // ( 0 0 1 ) + UniUpperMatrix< CompressedMatrix > 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 > 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 B( { { 1.0, 8.0, -2.0 }, + { 0.0, 1.0, -1.0 }, + { 0.0, 0.0, 1.0 } } ); + + UniUpperMatrix< DynamicMatrix > C( B ); // OK + + // Assignment of a non-uniupper dense matrix + StaticMatrix 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 > 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 > 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 > A1( 4 ), A2( 4 ); + + // Setup of a 4-dimensional vector + // + // v = ( 0 1 2 3 ) + // + DynamicVector 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 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 A( 5, 5 ); + + // 5x5 row-major uniupper dynamic matrix with default initialized lower matrix + UniUpperMatrix< DynamicMatrix > 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 > 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 A( 3, 3 ); + CompressedMatrix B( 3, 3 ); + + UniUpperMatrix< DynamicMatrix > C( 3 ); + UniUpperMatrix< CompressedMatrix > D( 3 ); + + UniUpperMatrix< HybridMatrix > E; + UniUpperMatrix< StaticMatrix > F; + + DynamicMatrix G( 3, 3 ); // Initialized as strictly upper matrix + CompressedMatrix 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 > A; + UniUpperMatrix< DynamicMatrix > B; + DynamicMatrix 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 > A; + DynamicVector 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 > A, C; + DynamicMatrix 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 > 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::value // Storage order of the adapted matrix + , bool DF = IsDenseMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public DenseMatrix< UniUpperMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the dense matrix. + typedef TransposeType_ TT; //!< Transpose type of the dense matrix. + typedef ElementType_ ET; //!< Element type of the dense matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef UniUpperMatrix This; //!< Type of this UniUpperMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this UniUpperMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef UniUpperMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef UniLowerMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef SIMDType_ SIMDType; //!< SIMD type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef UniUpperProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant matrix value. + typedef ConstPointer_ ConstPointer; //!< Pointer to a constant matrix value. + typedef ConstIterator_ 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::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_ ValueType; //!< Type of the underlying elements. + typedef UniUpperProxy PointerType; //!< Pointer return type. + typedef UniUpperProxy 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 > 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 > 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, UniUpperMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UniUpperMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, UniUpperMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UniUpperMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, UniUpperMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UniUpperMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline UniUpperMatrix& operator*=( const Matrix& 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& 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& 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::value == Columns::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::UniUpperMatrix() + : matrix_() // The adapted dense matrix +{ + for( size_t i=0UL; i::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::UniUpperMatrix( const A1& a1 ) + : matrix_( construct( a1, typename IsResizable::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::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 > 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::UniUpperMatrix( initializer_list< initializer_list > 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 > 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::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 > 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::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::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::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::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::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::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::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::Reference + UniUpperMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename UniUpperMatrix::ConstReference + UniUpperMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename UniUpperMatrix::Reference + UniUpperMatrix::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::ConstReference + UniUpperMatrix::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::ConstPointer + UniUpperMatrix::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::ConstPointer + UniUpperMatrix::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::Iterator + UniUpperMatrix::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::ConstIterator + UniUpperMatrix::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::ConstIterator + UniUpperMatrix::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::Iterator + UniUpperMatrix::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::ConstIterator + UniUpperMatrix::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::ConstIterator + UniUpperMatrix::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& + UniUpperMatrix::operator=( const ElementType& rhs ) +{ + if( SO ) { + for( size_t j=1UL; j > 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& + UniUpperMatrix::operator=( initializer_list< initializer_list > 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 > 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& + UniUpperMatrix::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& + UniUpperMatrix::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& + UniUpperMatrix::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, UniUpperMatrix& > + UniUpperMatrix::operator=( const Matrix& rhs ) +{ + if( IsStrictlyTriangular::value || ( !IsUniUpper::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, UniUpperMatrix& > + UniUpperMatrix::operator=( const Matrix& rhs ) +{ + if( IsStrictlyTriangular::value || ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" ); + } + + if( IsUniUpper::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, UniUpperMatrix& > + UniUpperMatrix::operator+=( const Matrix& rhs ) +{ + if( IsLower::value || IsUniTriangular::value || + ( !IsStrictlyUpper::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, UniUpperMatrix& > + UniUpperMatrix::operator+=( const Matrix& rhs ) +{ + if( IsLower::value || IsUniTriangular::value || + ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" ); + } + + if( IsStrictlyUpper::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ 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, UniUpperMatrix& > + UniUpperMatrix::operator-=( const Matrix& rhs ) +{ + if( IsLower::value || IsUniTriangular::value || + ( !IsStrictlyUpper::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, UniUpperMatrix& > + UniUpperMatrix::operator-=( const Matrix& rhs ) +{ + if( IsLower::value || IsUniTriangular::value || + ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" ); + } + + if( IsStrictlyUpper::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ 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& + UniUpperMatrix::operator*=( const Matrix& 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::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::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::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::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::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::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::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::reset() +{ + using blaze::clear; + + if( SO ) { + for( size_t j=1UL; j // Storage order of the adapted dense matrix +inline void UniUpperMatrix::reset( size_t i ) +{ + using blaze::clear; + + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted dense matrix +inline void UniUpperMatrix::clear() +{ + using blaze::clear; + + if( IsResizable::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::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 // Storage order of the adapted dense matrix +inline void UniUpperMatrix::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::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::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::maxNonZeros() noexcept +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + return maxNonZeros( Rows::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::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::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::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::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::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::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::SIMDType + UniUpperMatrix::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::SIMDType + UniUpperMatrix::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::SIMDType + UniUpperMatrix::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::construct( size_t n, TrueType ) +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + MT tmp( n, n, ElementType() ); + + for( size_t i=0UL; i // Storage order of the adapted dense matrix +inline const MT UniUpperMatrix::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 // 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::construct( const Matrix& m, T ) +{ + const MT tmp( ~m ); + + if( IsStrictlyTriangular::value || ( !IsUniUpper::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public SparseMatrix< UniUpperMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the sparse matrix. + typedef TransposeType_ TT; //!< Transpose type of the sparse matrix. + typedef ElementType_ ET; //!< Element type of the sparse matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef UniUpperMatrix This; //!< Type of this UniUpperMatrix instance. + typedef SparseMatrix BaseType; //!< Base type of this UniUpperMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef UniUpperMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef UniLowerMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef UniUpperProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef ConstIterator_ 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::Other > Other; + }; + //********************************************************************************************** + + //**Iterator class definition******************************************************************* + /*!\brief Iterator over the elements of the upper unitriangular matrix. + */ + class Iterator + { + public: + //**Type definitions************************************************************************* + typedef Iterator_ IteratorType; //!< Type of the underlying sparse matrix iterators. + + typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category. + typedef UniUpperElement 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& nonzeros ); + + inline UniUpperMatrix( const UniUpperMatrix& m ); + inline UniUpperMatrix( UniUpperMatrix&& m ) noexcept; + + template< typename MT2, bool SO2 > + inline UniUpperMatrix( const Matrix& 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, UniUpperMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UniUpperMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, UniUpperMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UniUpperMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, UniUpperMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UniUpperMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline UniUpperMatrix& operator*=( const Matrix& 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& 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::value == Columns::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::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::UniUpperMatrix( size_t n ) + : matrix_( n, n, n ) // The adapted sparse matrix +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + for( size_t i=0UL; i // Storage order of the adapted sparse matrix +inline UniUpperMatrix::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 // Storage order of the adapted sparse matrix +inline UniUpperMatrix::UniUpperMatrix( size_t n, const std::vector& nonzeros ) + : matrix_( n, n, nonzeros ) // The adapted sparse matrix +{ + BLAZE_CONSTRAINT_MUST_BE_RESIZABLE( MT ); + + for( size_t i=0UL; i // Storage order of the adapted sparse matrix +inline UniUpperMatrix::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::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::UniUpperMatrix( const Matrix& m ) + : matrix_( ~m ) // The adapted sparse matrix +{ + if( !IsUniUpper::value && !isUniUpper( matrix_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of uniupper matrix" ); + } + + if( !IsUniUpper::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::Reference + UniUpperMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename UniUpperMatrix::ConstReference + UniUpperMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename UniUpperMatrix::Reference + UniUpperMatrix::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::ConstReference + UniUpperMatrix::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::Iterator + UniUpperMatrix::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::ConstIterator + UniUpperMatrix::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::ConstIterator + UniUpperMatrix::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::Iterator + UniUpperMatrix::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::ConstIterator + UniUpperMatrix::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::ConstIterator + UniUpperMatrix::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& + UniUpperMatrix::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& + UniUpperMatrix::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, UniUpperMatrix& > + UniUpperMatrix::operator=( const Matrix& rhs ) +{ + if( IsStrictlyTriangular::value || ( !IsUniUpper::value && !isUniUpper( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" ); + } + + matrix_ = ~rhs; + + if( !IsUniUpper::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, UniUpperMatrix& > + UniUpperMatrix::operator=( const Matrix& rhs ) +{ + if( IsStrictlyTriangular::value || ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" ); + } + + if( IsUniUpper::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::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, UniUpperMatrix& > + UniUpperMatrix::operator+=( const Matrix& rhs ) +{ + if( IsLower::value || IsUniTriangular::value || + ( !IsStrictlyUpper::value && !isStrictlyUpper( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" ); + } + + matrix_ += ~rhs; + + if( !IsStrictlyUpper::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, UniUpperMatrix& > + UniUpperMatrix::operator+=( const Matrix& rhs ) +{ + if( IsLower::value || IsUniTriangular::value || + ( IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" ); + } + + if( IsStrictlyUpper::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ tmp( ~rhs ); + + if( !isStrictlyUpper( tmp ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" ); + } + + matrix_ += tmp; + } + + if( !IsStrictlyUpper::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, UniUpperMatrix& > + UniUpperMatrix::operator-=( const Matrix& rhs ) +{ + if( IsLower::value || IsUniTriangular::value || + ( !IsStrictlyUpper::value && !isStrictlyUpper( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" ); + } + + matrix_ -= ~rhs; + + if( !IsStrictlyUpper::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, UniUpperMatrix& > + UniUpperMatrix::operator-=( const Matrix& rhs ) +{ + if( IsLower::value || IsUniTriangular::value || + ( !IsSquare::value && !isSquare( ~rhs ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" ); + } + + if( IsStrictlyUpper::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ tmp( ~rhs ); + + if( !isStrictlyUpper( tmp ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to uniupper matrix" ); + } + + matrix_ -= tmp; + } + + if( !IsStrictlyUpper::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& + UniUpperMatrix::operator*=( const Matrix& 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::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::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::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::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::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::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::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::reset() +{ + if( SO ) { + for( size_t j=1UL; j // Storage order of the adapted sparse matrix +inline void UniUpperMatrix::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::clear() +{ + using blaze::clear; + + if( IsResizable::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::Iterator + UniUpperMatrix::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::Iterator + UniUpperMatrix::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::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::Iterator + UniUpperMatrix::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::Iterator + UniUpperMatrix::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::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 // Storage order of the adapted sparse matrix +inline void UniUpperMatrix::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::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::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::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::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::maxNonZeros() noexcept +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + return maxNonZeros( Rows::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::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::resetLower() +{ + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted sparse matrix +inline typename UniUpperMatrix::Iterator + UniUpperMatrix::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::ConstIterator + UniUpperMatrix::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::Iterator + UniUpperMatrix::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::ConstIterator + UniUpperMatrix::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::Iterator + UniUpperMatrix::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::ConstIterator + UniUpperMatrix::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 > 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::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::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::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::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::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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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_ ElementType; //!< Type of the represented matrix element. + typedef Iterator_ IteratorType; //!< Type of the underlying sparse matrix iterators. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef UniUpperValue ValueType; //!< The value type of the value-index-pair. + typedef size_t IndexType; //!< The index type of the value-index-pair. + typedef UniUpperValue Reference; //!< Reference return type. + typedef const UniUpperValue 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::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& UniUpperElement::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& UniUpperElement::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& UniUpperElement::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& UniUpperElement::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& UniUpperElement::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::Pointer UniUpperElement::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::Reference UniUpperElement::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::IndexType UniUpperElement::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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 > +{ + 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_ RepresentedType; + + //! Value type of the represented complex element. + typedef typename If_< IsComplex + , ComplexType + , BuiltinType >::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::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::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& UniUpperProxy::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& UniUpperProxy::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& UniUpperProxy::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& UniUpperProxy::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& UniUpperProxy::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& UniUpperProxy::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::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::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::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::RepresentedType UniUpperProxy::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::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::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::ValueType UniUpperProxy::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::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::ValueType UniUpperProxy::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::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& proxy ); + +template< typename MT > +inline void clear( const UniUpperProxy& proxy ); + +template< typename MT > +inline void invert( const UniUpperProxy& proxy ); + +template< typename MT > +inline bool isDefault( const UniUpperProxy& proxy ); + +template< typename MT > +inline bool isReal( const UniUpperProxy& proxy ); + +template< typename MT > +inline bool isZero( const UniUpperProxy& proxy ); + +template< typename MT > +inline bool isOne( const UniUpperProxy& proxy ); + +template< typename MT > +inline bool isnan( const UniUpperProxy& 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& 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& 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& 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& 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& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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 > +{ + 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_ RepresentedType; //!< Type of the represented matrix element. + + //! Value type of the represented complex element. + typedef typename If_< IsComplex + , ComplexType + , BuiltinType >::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::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& UniUpperValue::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& UniUpperValue::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& UniUpperValue::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& UniUpperValue::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& UniUpperValue::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& UniUpperValue::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::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::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::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::RepresentedType UniUpperValue::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::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::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::ValueType UniUpperValue::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::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::ValueType UniUpperValue::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::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& value ); + +template< typename MT > +inline void clear( const UniUpperValue& value ); + +template< typename MT > +inline void invert( const UniUpperValue& value ); + +template< typename MT > +inline bool isDefault( const UniUpperValue& value ); + +template< typename MT > +inline bool isReal( const UniUpperValue& value ); + +template< typename MT > +inline bool isZero( const UniUpperValue& value ); + +template< typename MT > +inline bool isOne( const UniUpperValue& value ); + +template< typename MT > +inline bool isnan( const UniUpperValue& 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& 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& 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& 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& 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& 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& 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& 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& 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 +#include + + +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 > A; + + // Definition of a resizable column-major dense upper matrix based on HybridMatrix + blaze::UpperMatrix< blaze::HybridMatrix B; + + // Definition of a resizable row-major dense upper matrix based on DynamicMatrix + blaze::UpperMatrix< blaze::DynamicMatrix > C; + + // Definition of a fixed-size row-major dense upper matrix based on CustomMatrix + blaze::UpperMatrix< blaze::CustomMatrix > D; + + // Definition of a compressed row-major single precision upper matrix + blaze::UpperMatrix< blaze::CompressedMatrix > 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: +// +// -# \ref uppermatrix_square +// -# \ref uppermatrix_upper +// -# \ref uppermatrix_initialization +// -# \ref uppermatrix_storage +// +// \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 > 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 > A; + + // Compilation error: the provided matrix type is not a square matrix type + UpperMatrix< StaticMatrix > 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 > 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 B( { { 3.0, 8.0, -2.0 }, + { 0.0, 0.0, -1.0 }, + { 0.0, 0.0, 4.0 } } ); + + UpperMatrix< DynamicMatrix > C( B ); // OK + + // Assignment of a non-upper dense matrix + StaticMatrix 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 > 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 > 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 > A1( 4 ), A2( 4 ); + + // Setup of a 4-dimensional vector + // + // v = ( 0 1 2 3 ) + // + DynamicVector 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 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 A( 5, 5 ); + + // 5x5 row-major upper dynamic matrix with default initialized lower matrix + UpperMatrix< DynamicMatrix > 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 A( 3, 3 ); + CompressedMatrix B( 3, 3 ); + + UpperMatrix< DynamicMatrix > C( 3 ); + UpperMatrix< CompressedMatrix > D( 3 ); + + UpperMatrix< HybridMatrix > E; + UpperMatrix< StaticMatrix > 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 > > 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 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 > A; + UpperMatrix< DynamicMatrix > B; + DynamicMatrix 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 > A; + DynamicVector 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 > A, C; + DynamicMatrix 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 > 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::value // Storage order of the adapted matrix + , bool DF = IsDenseMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public DenseMatrix< UpperMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the dense matrix. + typedef TransposeType_ TT; //!< Transpose type of the dense matrix. + typedef ElementType_ ET; //!< Element type of the dense matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef UpperMatrix This; //!< Type of this UpperMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this UpperMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef UpperMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef LowerMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef SIMDType_ SIMDType; //!< SIMD type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef UpperProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant matrix value. + typedef ConstPointer_ ConstPointer; //!< Pointer to a constant matrix value. + typedef ConstIterator_ 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::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_ ValueType; //!< Type of the underlying elements. + typedef UpperProxy PointerType; //!< Pointer return type. + typedef UpperProxy 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 > 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 > 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, UpperMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UpperMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, UpperMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UpperMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, UpperMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UpperMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline UpperMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, UpperMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& 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& m ); + + template< typename MT2, bool SO2, bool DF2 > + friend MT2& derestrict( UpperMatrix& 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::value == Columns::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::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::UpperMatrix( const A1& a1 ) + : matrix_( construct( a1, typename IsResizable::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::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 > 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::UpperMatrix( initializer_list< initializer_list > 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 > 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::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 > 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::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::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::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::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::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::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::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::Reference + UpperMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename UpperMatrix::ConstReference + UpperMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted dense matrix +inline typename UpperMatrix::Reference + UpperMatrix::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::ConstReference + UpperMatrix::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::ConstPointer + UpperMatrix::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::ConstPointer + UpperMatrix::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::Iterator + UpperMatrix::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::ConstIterator + UpperMatrix::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::ConstIterator + UpperMatrix::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::Iterator + UpperMatrix::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::ConstIterator + UpperMatrix::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::ConstIterator + UpperMatrix::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& + UpperMatrix::operator=( const ElementType& rhs ) +{ + if( SO ) { + for( size_t j=0UL; j > 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& + UpperMatrix::operator=( initializer_list< initializer_list > 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 > 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& + UpperMatrix::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& + UpperMatrix::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& + UpperMatrix::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, UpperMatrix& > + UpperMatrix::operator=( const Matrix& rhs ) +{ + if( !IsUpper::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, UpperMatrix& > + UpperMatrix::operator=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" ); + } + + if( IsUpper::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, UpperMatrix& > + UpperMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsUpper::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, UpperMatrix& > + UpperMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" ); + } + + if( IsUpper::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ 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, UpperMatrix& > + UpperMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsUpper::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, UpperMatrix& > + UpperMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" ); + } + + if( IsUpper::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ 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& + UpperMatrix::operator*=( const Matrix& 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, UpperMatrix >& + UpperMatrix::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, UpperMatrix >& + UpperMatrix::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::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::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::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::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::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::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::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::reset() +{ + using blaze::clear; + + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted dense matrix +inline void UpperMatrix::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 // Storage order of the adapted dense matrix +inline void UpperMatrix::clear() +{ + using blaze::clear; + + if( IsResizable::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::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::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::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& UpperMatrix::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::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::maxNonZeros() noexcept +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + return maxNonZeros( Rows::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::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::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::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::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::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::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::SIMDType + UpperMatrix::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::SIMDType + UpperMatrix::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::SIMDType + UpperMatrix::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::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::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 // 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::construct( const Matrix& m, T ) +{ + const MT tmp( ~m ); + + if( !IsUpper::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public SparseMatrix< UpperMatrix, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef OppositeType_ OT; //!< Opposite type of the sparse matrix. + typedef TransposeType_ TT; //!< Transpose type of the sparse matrix. + typedef ElementType_ ET; //!< Element type of the sparse matrix. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef UpperMatrix This; //!< Type of this UpperMatrix instance. + typedef SparseMatrix BaseType; //!< Base type of this UpperMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef UpperMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef LowerMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef ET ElementType; //!< Type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef UpperProxy Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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::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& nonzeros ); + + inline UpperMatrix( const UpperMatrix& m ); + inline UpperMatrix( UpperMatrix&& m ) noexcept; + + template< typename MT2, bool SO2 > + inline UpperMatrix( const Matrix& 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, UpperMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UpperMatrix& > operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, UpperMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UpperMatrix& > operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< IsComputation, UpperMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< IsComputation, UpperMatrix& > operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline UpperMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, UpperMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& m ); + + template< typename MT2, bool SO2, bool DF2 > + friend MT2& derestrict( UpperMatrix& 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::value == Columns::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::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::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::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::UpperMatrix( size_t n, const std::vector& 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::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::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::UpperMatrix( const Matrix& m ) + : matrix_( ~m ) // The adapted sparse matrix +{ + if( !IsUpper::value && !isUpper( matrix_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of upper matrix" ); + } + + if( !IsUpper::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::Reference + UpperMatrix::operator()( size_t i, size_t j ) +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename UpperMatrix::ConstReference + UpperMatrix::operator()( size_t i, size_t j ) const +{ + BLAZE_USER_ASSERT( i // Storage order of the adapted sparse matrix +inline typename UpperMatrix::Reference + UpperMatrix::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::ConstReference + UpperMatrix::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::Iterator + UpperMatrix::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::ConstIterator + UpperMatrix::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::ConstIterator + UpperMatrix::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::Iterator + UpperMatrix::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::ConstIterator + UpperMatrix::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::ConstIterator + UpperMatrix::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& + UpperMatrix::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& + UpperMatrix::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, UpperMatrix& > + UpperMatrix::operator=( const Matrix& rhs ) +{ + if( !IsUpper::value && !isUpper( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" ); + } + + matrix_ = ~rhs; + + if( !IsUpper::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, UpperMatrix& > + UpperMatrix::operator=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" ); + } + + if( IsUpper::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::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, UpperMatrix& > + UpperMatrix::operator+=( const Matrix& rhs ) +{ + if( !IsUpper::value && !isUpper( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" ); + } + + matrix_ += ~rhs; + + if( !IsUpper::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, UpperMatrix& > + UpperMatrix::operator+=( const Matrix& rhs ) +{ + if( IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" ); + } + + if( IsUpper::value ) { + matrix_ += ~rhs; + } + else { + const ResultType_ tmp( ~rhs ); + + if( !isUpper( tmp ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" ); + } + + matrix_ += tmp; + } + + if( !IsUpper::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, UpperMatrix& > + UpperMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsUpper::value && !isUpper( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" ); + } + + matrix_ -= ~rhs; + + if( !IsUpper::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, UpperMatrix& > + UpperMatrix::operator-=( const Matrix& rhs ) +{ + if( !IsSquare::value && !isSquare( ~rhs ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" ); + } + + if( IsUpper::value ) { + matrix_ -= ~rhs; + } + else { + const ResultType_ tmp( ~rhs ); + + if( !isUpper( tmp ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to upper matrix" ); + } + + matrix_ -= tmp; + } + + if( !IsUpper::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& + UpperMatrix::operator*=( const Matrix& 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::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, UpperMatrix >& + UpperMatrix::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, UpperMatrix >& + UpperMatrix::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::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::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::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::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::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::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::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::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::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::Iterator + UpperMatrix::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::Iterator + UpperMatrix::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::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::Iterator + UpperMatrix::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::Iterator + UpperMatrix::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::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::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::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::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::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& + UpperMatrix::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& + UpperMatrix::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::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::maxNonZeros() noexcept +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_RESIZABLE( MT ); + + return maxNonZeros( Rows::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::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::resetLower() +{ + if( SO ) { + for( size_t j=0UL; j // Storage order of the adapted sparse matrix +inline typename UpperMatrix::Iterator + UpperMatrix::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::ConstIterator + UpperMatrix::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::Iterator + UpperMatrix::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::ConstIterator + UpperMatrix::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::Iterator + UpperMatrix::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::ConstIterator + UpperMatrix::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 > 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::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::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::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::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::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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 > 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, ElementType_ > +{ + private: + //**Type definitions**************************************************************************** + //! Reference type of the underlying matrix type. + typedef AddConst_< typename MT::Reference > ReferenceType; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef ElementType_ RepresentedType; //!< Type of the represented matrix element. + typedef AddReference_ 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 list ) const; + + template< typename T > + inline const UpperProxy& operator=( initializer_list< initializer_list > 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::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::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& UpperProxy::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& UpperProxy::operator=( initializer_list 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& UpperProxy::operator=( initializer_list< initializer_list > 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& UpperProxy::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& UpperProxy::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& UpperProxy::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& UpperProxy::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& UpperProxy::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::RawReference UpperProxy::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::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::operator ConstReference() const noexcept +{ + return static_cast( value_ ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name UpperProxy global functions */ +//@{ +template< typename MT > +inline void reset( const UpperProxy& proxy ); + +template< typename MT > +inline void clear( const UpperProxy& proxy ); + +template< typename MT > +inline bool isDefault( const UpperProxy& proxy ); + +template< typename MT > +inline bool isReal( const UpperProxy& proxy ); + +template< typename MT > +inline bool isZero( const UpperProxy& proxy ); + +template< typename MT > +inline bool isOne( const UpperProxy& proxy ); + +template< typename MT > +inline bool isnan( const UpperProxy& 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& 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& 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& 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& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 dot( const int n, const complex* x, const int incX, + const complex* y, const int incY ); + +complex dot( const int n, const complex* x, const int incX, + const complex* y, const int incY ); + +template< typename VT1, bool TF1, typename VT2, bool TF2 > +ElementType_ dot( const DenseVector& x, const DenseVector& 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 dot( const int n, const complex* x, const int incX, + const complex* y, const int incY ) +{ + complex 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 dot( const int n, const complex* x, const int incX, + const complex* y, const int incY ) +{ + complex 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, or +// \c complex 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_ dot( const DenseVector& x, const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + const int n( numeric_cast( (~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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 alpha, const complex* A, + int lda, const complex* B, int ldb, complex 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 alpha, const complex* A, + int lda, const complex* B, int ldb, complex 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& C, const DenseMatrix& A, + const DenseMatrix& 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 alpha, const complex* A, + int lda, const complex* B, int ldb, complex beta, + complex* 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 alpha, const complex* A, + int lda, const complex* B, int ldb, complex beta, + complex* 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, and \c complex 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& C, const DenseMatrix& A, + const DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + const int m ( numeric_cast( (~A).rows() ) ); + const int n ( numeric_cast( (~B).columns() ) ); + const int k ( numeric_cast( (~A).columns() ) ); + const int lda( numeric_cast( (~A).spacing() ) ); + const int ldb( numeric_cast( (~B).spacing() ) ); + const int ldc( numeric_cast( (~C).spacing() ) ); + + gemm( ( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 alpha, const complex* A, int lda, + const complex* x, int incX, complex beta, + complex* y, int incY ); + +BLAZE_ALWAYS_INLINE void gemv( CBLAS_ORDER layout, CBLAS_TRANSPOSE transA, int m, int n, + complex alpha, const complex* A, int lda, + const complex* x, int incX, complex beta, + complex* y, int incY ); + +template< typename VT1, typename MT1, bool SO, typename VT2, typename ST > +BLAZE_ALWAYS_INLINE void gemv( DenseVector& y, const DenseMatrix& A, + const DenseVector& x, ST alpha, ST beta ); + +template< typename VT1, typename VT2, typename MT1, bool SO, typename ST > +BLAZE_ALWAYS_INLINE void gemv( DenseVector& y, const DenseVector& x, + const DenseMatrix& 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 alpha, const complex* A, int lda, + const complex* x, int incX, complex beta, + complex* 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 alpha, const complex* A, int lda, + const complex* x, int incX, complex beta, + complex* 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, or \c complex 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& y, const DenseMatrix& A, + const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + const int m ( numeric_cast( (~A).rows() ) ); + const int n ( numeric_cast( (~A).columns() ) ); + const int lda( numeric_cast( (~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, or \c complex 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& y, const DenseVector& x, + const DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + const int m ( numeric_cast( (~A).rows() ) ); + const int n ( numeric_cast( (~A).columns() ) ); + const int lda( numeric_cast( (~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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 alpha, const complex* A, int lda, + complex* 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 alpha, const complex* A, int lda, + complex* B, int ldb ); + +template< typename MT1, bool SO1, typename MT2, bool SO2, typename ST > +BLAZE_ALWAYS_INLINE void trmm( DenseMatrix& B, const DenseMatrix& 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 alpha, const complex* A, int lda, + complex* 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 alpha, const complex* A, int lda, + complex* 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, and \c complex 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& B, const DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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( (~B).rows() ) ); + const int n ( numeric_cast( (~B).columns() ) ); + const int lda( numeric_cast( (~A).spacing() ) ); + const int ldb( numeric_cast( (~B).spacing() ) ); + + trmm( ( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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* A, int lda, + complex* x, int incX ); + +BLAZE_ALWAYS_INLINE void trmv( CBLAS_ORDER order, CBLAS_UPLO uplo, CBLAS_TRANSPOSE transA, + CBLAS_DIAG diag, int n, const complex* A, int lda, + complex* x, int incX ); + +template< typename VT, typename MT, bool SO > +BLAZE_ALWAYS_INLINE void trmv( DenseVector& x, const DenseMatrix& A, + CBLAS_UPLO uplo ); + +template< typename VT, typename MT, bool SO > +BLAZE_ALWAYS_INLINE void trmv( DenseVector& x, const DenseMatrix& 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* A, int lda, + complex* 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* A, int lda, + complex* 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, or \c complex 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& x, const DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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( (~A).rows() ) ); + const int lda( numeric_cast( (~A).spacing() ) ); + + trmv( ( IsRowMajorMatrix::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, or \c complex 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& x, const DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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( (~A).rows() ) ); + const int lda( numeric_cast( (~A).spacing() ) ); + + trmv( ( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 alpha, const complex* A, int lda, + complex* 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 alpha, const complex* A, int lda, + complex* B, int ldb ); + +template< typename MT, bool SO, typename VT, bool TF, typename ST > +BLAZE_ALWAYS_INLINE void trsm( const DenseMatrix& A, DenseVector& 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& A, DenseMatrix& 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 alpha, const complex* A, int lda, + complex* 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 alpha, const complex* A, int lda, + complex* 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, and +// \c complex 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& A, DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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( (~b).size() ) ):( 1 ) ); + const int n ( ( side == CblasRight )?( numeric_cast( (~b).size() ) ):( 1 ) ); + const int lda( numeric_cast( (~A).spacing() ) ); + const int ldb( ( IsRowMajorMatrix::value )?( n ):( m ) ); + + trsm( ( IsRowMajorMatrix::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, and \c complex 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& A, DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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( (~B).rows() ) ); + const int n ( numeric_cast( (~B).columns() ) ); + const int lda( numeric_cast( (~A).spacing() ) ); + const int ldb( numeric_cast( (~B).spacing() ) ); + + trsm( ( IsRowMajorMatrix::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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, or complex), a compilation error is created. +*/ +#define BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE(T) \ + static_assert( ::blaze::IsBLASCompatible::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, +// or complex), a compilation error is created. +*/ +#define BLAZE_CONSTRAINT_MUST_NOT_BE_BLAS_COMPATIBLE_TYPE(T) \ + static_assert( !::blaze::IsBLASCompatible::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 +#include +#include +#include +#include + + +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, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::Columns > \ + >::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, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::SizeT<0UL> > \ + , ::blaze::Not< ::blaze::Equal< ::blaze::Columns, ::blaze::Columns > > \ + >::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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, +// long double, 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::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, +// long double, 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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 +#include +#include +#include +#include +#include +#include +#include +#include + + +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::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::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 \ + , ::blaze::IsMatrix \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Rows, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::Rows > > \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Columns, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::Columns > > \ + >::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 \ + , ::blaze::IsMatrix \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Rows, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::Rows > > \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Columns, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::Columns > > > \ + >::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 +#include +#include +#include +#include +#include +#include +#include +#include + + +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::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::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 \ + , ::blaze::IsMatrix \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Columns, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::Rows > > \ + >::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 \ + , ::blaze::IsMatrix \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Columns, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::Rows > > > \ + >::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 +#include +#include +#include +#include +#include +#include +#include +#include + + +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::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::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 \ + , ::blaze::IsMatrix \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Rows, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::Rows > > \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Columns, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::Columns > > \ + >::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 \ + , ::blaze::IsMatrix \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Rows, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::Rows > > \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Columns, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::Columns > > > \ + >::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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::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::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 \ + , ::blaze::IsColumnVector \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Columns, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::Size > > \ + >::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 \ + , ::blaze::IsColumnVector \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Columns, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Columns, ::blaze::Size > > > \ + >::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 +#include +#include +#include +#include + + +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, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::Rows > \ + >::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, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::SizeT<0UL> > \ + , ::blaze::Not< ::blaze::Equal< ::blaze::Rows, ::blaze::Rows > > \ + >::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 +#include +#include +#include +#include + + +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, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::Size > \ + >::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, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Not< ::blaze::Equal< ::blaze::Size, ::blaze::Size > > \ + >::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 +#include + + +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::value && \ + ::blaze::StorageOrder::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::value && \ + ::blaze::IsMatrix::value && \ + ::blaze::StorageOrder::value == ::blaze::StorageOrder::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::value && \ + ::blaze::IsMatrix::value && \ + ::blaze::StorageOrder::value != ::blaze::StorageOrder::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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::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::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 \ + , ::blaze::IsMatrix \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::Rows > > \ + >::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 \ + , ::blaze::IsMatrix \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Rows, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::Rows > > > \ + >::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 + + +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::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::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 +#include + + +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::value && \ + ::blaze::TransposeFlag::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::value && \ + ::blaze::IsVector::value && \ + ::blaze::TransposeFlag::value == ::blaze::TransposeFlag::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::value && \ + ::blaze::IsVector::value && \ + ::blaze::TransposeFlag::value != ::blaze::TransposeFlag::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 +#include +#include +#include +#include + + +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::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::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 \ + , ::blaze::IsRowVector \ + >::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 \ + , ::blaze::IsRowVector > \ + >::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 + + +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::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::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 +#include +#include +#include +#include +#include +#include +#include +#include + + +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::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::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 \ + , ::blaze::IsRowVector > \ + , ::blaze::And< ::blaze::IsColumnVector \ + , ::blaze::IsColumnVector > > \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::Size > > \ + >::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 \ + , ::blaze::IsRowVector > \ + , ::blaze::And< ::blaze::IsColumnVector \ + , ::blaze::IsColumnVector > > \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::Size > > > \ + >::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 +#include +#include +#include +#include +#include +#include +#include +#include + + +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::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::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 \ + , ::blaze::IsRowVector > \ + , ::blaze::And< ::blaze::IsColumnVector \ + , ::blaze::IsColumnVector > > \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::Size > > \ + >::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 \ + , ::blaze::IsRowVector > \ + , ::blaze::And< ::blaze::IsColumnVector \ + , ::blaze::IsColumnVector > > \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::Size > > > \ + >::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 +#include +#include +#include +#include +#include +#include +#include +#include + + +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::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::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 \ + , ::blaze::IsRowVector > \ + , ::blaze::And< ::blaze::IsColumnVector \ + , ::blaze::IsColumnVector > > \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::Size > > \ + >::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 \ + , ::blaze::IsRowVector > \ + , ::blaze::And< ::blaze::IsColumnVector \ + , ::blaze::IsColumnVector > > \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::Size > > > \ + >::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 +#include +#include +#include +#include +#include +#include +#include +#include + + +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::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::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 \ + , ::blaze::IsRowVector > \ + , ::blaze::And< ::blaze::IsColumnVector \ + , ::blaze::IsColumnVector > > \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::Size > > \ + >::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 \ + , ::blaze::IsRowVector > \ + , ::blaze::And< ::blaze::IsColumnVector \ + , ::blaze::IsColumnVector > > \ + , ::blaze::Or< ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::SizeT<0UL> > \ + , ::blaze::Equal< ::blaze::Size, ::blaze::Size > > > \ + >::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 + + +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::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::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 + + +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::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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 UnalignedUnpadded; + + // Definition of a custom column-major matrix for unaligned but padded 'float' arrays + typedef CustomMatrix UnalignedPadded; + + // Definition of a custom row-major matrix for aligned, unpadded 'double' arrays + typedef CustomMatrix AlignedUnpadded; + + // Definition of a custom column-major matrix for aligned, padded 'complex' arrays + typedef CustomMatrix,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: +// +// -# \ref custommatrix_memory_management +// -# \ref custommatrix_copy_operations +// -# \ref custommatrix_alignment +// -# \ref custommatrix_padding +// +// \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 vec( 12UL ); + CustomMatrix 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 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 C( allocate( 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 CustomType; + + std::vector 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 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( 40UL ); // Is guaranteed to be 32-bit aligned + CustomMatrix 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 CustomType; + + // Creating padded custom 3x3 matrix with an additional padding element in each row + CustomType A( allocate( 12UL ), 3UL, 3UL, 4UL, Deallocate() ); + CustomType B( allocate( 12UL ), 3UL, 3UL, 4UL, Deallocate() ); + CustomType C( allocate( 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 CustomType; + + // Creating unpadded custom 3x3 matrix + CustomType A( allocate( 12UL ), 3UL, 3UL, 4UL, Deallocate() ); + CustomType B( allocate( 12UL ), 3UL, 3UL, 4UL, Deallocate() ); + CustomType C( allocate( 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 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 B( allocate( 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 C( 2, 3 ); // Empty row-major sparse single precision matrix + DynamicMatrix D( 3, 2, 4.0F ); // Directly, homogeneously initialized single precision 3x2 matrix + + DynamicMatrix E( A ); // Creation of a new row-major matrix as a copy of A + DynamicMatrix 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, SO > +{ + public: + //**Type definitions**************************************************************************** + typedef CustomMatrix This; //!< Type of this CustomMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this CustomMatrix instance. + typedef DynamicMatrix ResultType; //!< Result type for expression template evaluations. + typedef DynamicMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef DynamicMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef Type ElementType; //!< Type of the matrix elements. + typedef SIMDTrait_ 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 Iterator; //!< Iterator over non-constant elements. + typedef DenseIterator 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 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::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::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 > > + 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 > 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& rhs ); + template< typename MT, bool SO2 > inline CustomMatrix& operator+=( const Matrix& rhs ); + template< typename MT, bool SO2 > inline CustomMatrix& operator-=( const Matrix& rhs ); + template< typename MT, bool SO2 > inline CustomMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_, CustomMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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 > > + 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_ >::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_ >::value && + HasSIMDAdd< Type, ElementType_ >::value && + !IsDiagonal::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_ >::value && + HasSIMDSub< Type, ElementType_ >::value && + !IsDiagonal::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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_ > assign( const DenseMatrix& rhs ); + + template< typename MT > + inline EnableIf_ > assign( const DenseMatrix& rhs ); + + template< typename MT > inline void assign( const DenseMatrix& rhs ); + template< typename MT > inline void assign( const SparseMatrix& rhs ); + template< typename MT > inline void assign( const SparseMatrix& rhs ); + + template< typename MT > + inline DisableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT > + inline EnableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT > inline void addAssign( const DenseMatrix& rhs ); + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + + template< typename MT > + inline DisableIf_ > subAssign( const DenseMatrix& rhs ); + + template< typename MT > + inline EnableIf_ > subAssign( const DenseMatrix& rhs ); + + template< typename MT > inline void subAssign( const DenseMatrix& rhs ); + template< typename MT > inline void subAssign( const SparseMatrix& rhs ); + template< typename MT > inline void subAssign( const SparseMatrix& 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 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::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::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::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::value && ( nn_ < nextMultiple( n_, SIMDSIZE ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Insufficient capacity for padded matrix" ); + } + + v_.reset( ptr, NoDelete() ); + + if( PF && IsVectorizable::value ) { + for( size_t i=0UL; i // Storage order +template< typename Deleter // Type of the custom deleter + , typename > // Type restriction on the custom deleter +inline CustomMatrix::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::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::value && ( nn_ < nextMultiple( n_, SIMDSIZE ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Insufficient capacity for padded matrix" ); + } + + v_.reset( ptr, d ); + + if( PF && IsVectorizable::value ) { + for( size_t i=0UL; i // Storage order +inline CustomMatrix::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::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::Reference + CustomMatrix::operator()( size_t i, size_t j ) noexcept +{ + BLAZE_USER_ASSERT( i // Storage order +inline typename CustomMatrix::ConstReference + CustomMatrix::operator()( size_t i, size_t j ) const noexcept +{ + BLAZE_USER_ASSERT( i // Storage order +inline typename CustomMatrix::Reference + CustomMatrix::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::ConstReference + CustomMatrix::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::Pointer + CustomMatrix::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::ConstPointer + CustomMatrix::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::Pointer + CustomMatrix::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::ConstPointer + CustomMatrix::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::Iterator + CustomMatrix::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::ConstIterator + CustomMatrix::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::ConstIterator + CustomMatrix::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::Iterator + CustomMatrix::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::ConstIterator + CustomMatrix::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::ConstIterator + CustomMatrix::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& CustomMatrix::operator=( const Type& rhs ) +{ + for( size_t i=0UL; i 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& + CustomMatrix::operator=( initializer_list< initializer_list > 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 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& CustomMatrix::operator=( const Other (&array)[M][N] ) +{ + if( m_ != M || n_ != N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" ); + } + + for( size_t i=0UL; i // Storage order +inline CustomMatrix& CustomMatrix::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& + CustomMatrix::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& CustomMatrix::operator=( const Matrix& rhs ) +{ + typedef TransExprTrait_ TT; + typedef CTransExprTrait_ CT; + typedef InvExprTrait_ IT; + + if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( IsSame::value && (~rhs).isAliased( this ) ) { + transpose(); + } + else if( IsSame::value && (~rhs).isAliased( this ) ) { + ctranspose(); + } + else if( !IsSame::value && (~rhs).canAlias( this ) ) { + const ResultType_ tmp( ~rhs ); + smpAssign( *this, tmp ); + } + else { + if( IsSparseMatrix::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& CustomMatrix::operator+=( const Matrix& rhs ) +{ + if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& CustomMatrix::operator-=( const Matrix& rhs ) +{ + if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& CustomMatrix::operator*=( const Matrix& rhs ) +{ + if( m_ != n_ || (~rhs).rows() != m_ || (~rhs).columns() != n_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + const MultTrait_< ResultType, ResultType_ > 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_, CustomMatrix >& + CustomMatrix::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_, CustomMatrix >& + CustomMatrix::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::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::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::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::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::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::nonZeros() const +{ + size_t nonzeros( 0UL ); + + for( size_t i=0UL; i // Storage order +inline size_t CustomMatrix::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 // Storage order +inline void CustomMatrix::reset() +{ + using blaze::clear; + + for( size_t i=0UL; i // Storage order +inline void CustomMatrix::reset( size_t i ) +{ + using blaze::clear; + + BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" ); + for( size_t j=0UL; j // Storage order +inline void CustomMatrix::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& CustomMatrix::transpose() +{ + using std::swap; + + if( m_ != n_ ) { + BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" ); + } + + for( size_t i=1UL; i // Storage order +inline CustomMatrix& CustomMatrix::ctranspose() +{ + if( m_ != n_ ) { + BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" ); + } + + for( size_t i=0UL; i // Storage order +template< typename Other > // Data type of the scalar value +inline CustomMatrix& CustomMatrix::scale( const Other& scalar ) +{ + for( size_t i=0UL; i // Storage order +inline void CustomMatrix::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::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::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::reset( Type* ptr, size_t m, size_t n, Deleter d ) +{ + BLAZE_STATIC_ASSERT( !IsClass::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::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::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::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::SIMDType + CustomMatrix::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::SIMDType + CustomMatrix::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::SIMDType + CustomMatrix::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::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::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::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::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_::BLAZE_TEMPLATE VectorizedAssign > + CustomMatrix::assign( const DenseMatrix& 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 // Storage order +template< typename MT > // Type of the right-hand side dense matrix +inline EnableIf_::BLAZE_TEMPLATE VectorizedAssign > + CustomMatrix::assign( const DenseMatrix& 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::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 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 // Storage order +template< typename MT > // Type of the right-hand side dense matrix +inline void CustomMatrix::assign( const DenseMatrix& 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 // Storage order +template< typename MT > // Type of the right-hand side sparse matrix +inline void CustomMatrix::assign( const SparseMatrix& 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 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::assign( const SparseMatrix& 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 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_::BLAZE_TEMPLATE VectorizedAddAssign > + CustomMatrix::addAssign( const DenseMatrix& 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::value ) + { + v_[i*nn_+i] += (~rhs)(i,i); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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_::BLAZE_TEMPLATE VectorizedAddAssign > + CustomMatrix::addAssign( const DenseMatrix& 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::value ); + + for( size_t i=0UL; i::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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_ 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 // Storage order +template< typename MT > // Type of the right-hand side dense matrix +inline void CustomMatrix::addAssign( const DenseMatrix& 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::value && ii < jj ) break; + if( IsUpper::value && ii > jj ) continue; + + for( size_t i=ii; i::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jend ( ( IsLower::value ) + ?( min( ( IsStrictlyLower::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 // Storage order +template< typename MT > // Type of the right-hand side sparse matrix +inline void CustomMatrix::addAssign( const SparseMatrix& 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 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::addAssign( const SparseMatrix& 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 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_::BLAZE_TEMPLATE VectorizedSubAssign > + CustomMatrix::subAssign( const DenseMatrix& 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::value ) + { + v_[i*nn_+i] -= (~rhs)(i,i); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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_::BLAZE_TEMPLATE VectorizedSubAssign > + CustomMatrix::subAssign( const DenseMatrix& 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::value ); + + for( size_t i=0UL; i::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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_ 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 // Storage order +template< typename MT > // Type of the right-hand side dense matrix +inline void CustomMatrix::subAssign( const DenseMatrix& 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::value && ii < jj ) break; + if( IsUpper::value && ii > jj ) continue; + + for( size_t i=ii; i::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jend ( ( IsLower::value ) + ?( min( ( IsStrictlyLower::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 // Storage order +template< typename MT > // Type of the right-hand side sparse matrix +inline void CustomMatrix::subAssign( const SparseMatrix& 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 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::subAssign( const SparseMatrix& 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 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 : public DenseMatrix< CustomMatrix, true > +{ + public: + //**Type definitions**************************************************************************** + typedef CustomMatrix This; //!< Type of this CustomMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this CustomMatrix instance. + typedef DynamicMatrix ResultType; //!< Result type for expression template evaluations. + typedef DynamicMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef DynamicMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef Type ElementType; //!< Type of the matrix elements. + typedef SIMDTrait_ 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 Iterator; //!< Iterator over non-constant elements. + typedef DenseIterator 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 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::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::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 > > + 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 > 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& rhs ); + template< typename MT, bool SO > inline CustomMatrix& operator+=( const Matrix& rhs ); + template< typename MT, bool SO > inline CustomMatrix& operator-=( const Matrix& rhs ); + template< typename MT, bool SO > inline CustomMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_, CustomMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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 > > + 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_ >::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_ >::value && + HasSIMDAdd< Type, ElementType_ >::value && + !IsDiagonal::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_ >::value && + HasSIMDSub< Type, ElementType_ >::value && + !IsDiagonal::value }; + }; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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_ > assign( const DenseMatrix& rhs ); + + template< typename MT > + inline EnableIf_ > assign( const DenseMatrix& rhs ); + + template< typename MT > inline void assign( const DenseMatrix& rhs ); + template< typename MT > inline void assign( const SparseMatrix& rhs ); + template< typename MT > inline void assign( const SparseMatrix& rhs ); + + template< typename MT > + inline DisableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT > + inline EnableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT > inline void addAssign( const DenseMatrix& rhs ); + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + + template< typename MT > + inline DisableIf_ > subAssign ( const DenseMatrix& rhs ); + + template< typename MT > + inline EnableIf_ > subAssign ( const DenseMatrix& rhs ); + + template< typename MT > inline void subAssign( const DenseMatrix& rhs ); + template< typename MT > inline void subAssign( const SparseMatrix& rhs ); + template< typename MT > inline void subAssign( const SparseMatrix& 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 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::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::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::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::value && ( mm_ < nextMultiple( m_, SIMDSIZE ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Insufficient capacity for padded matrix" ); + } + + v_.reset( ptr, NoDelete() ); + + if( PF && IsVectorizable::value ) { + for( size_t j=0UL; j // Padding flag +template< typename Deleter // Type of the custom deleter + , typename > // Type restriction on the custom deleter +inline CustomMatrix::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::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::value && ( mm_ < nextMultiple( m_, SIMDSIZE ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Insufficient capacity for padded matrix" ); + } + + v_.reset( ptr, d ); + + if( PF && IsVectorizable::value ) { + for( size_t j=0UL; j // Padding flag +inline CustomMatrix::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::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::Reference + CustomMatrix::operator()( size_t i, size_t j ) noexcept +{ + BLAZE_USER_ASSERT( i // Padding flag +inline typename CustomMatrix::ConstReference + CustomMatrix::operator()( size_t i, size_t j ) const noexcept +{ + BLAZE_USER_ASSERT( i // Padding flag +inline typename CustomMatrix::Reference + CustomMatrix::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::ConstReference + CustomMatrix::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::Pointer + CustomMatrix::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::ConstPointer + CustomMatrix::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::Pointer + CustomMatrix::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::ConstPointer + CustomMatrix::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::Iterator + CustomMatrix::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::ConstIterator + CustomMatrix::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::ConstIterator + CustomMatrix::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::Iterator + CustomMatrix::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::ConstIterator + CustomMatrix::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::ConstIterator + CustomMatrix::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& CustomMatrix::operator=( const Type& rhs ) +{ + for( size_t j=0UL; j 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& + CustomMatrix::operator=( initializer_list< initializer_list > 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 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& + CustomMatrix::operator=( const Other (&array)[M][N] ) +{ + if( m_ != M || n_ != N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" ); + } + + for( size_t j=0UL; j // Padding flag +inline CustomMatrix& + CustomMatrix::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& + CustomMatrix::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& + CustomMatrix::operator=( const Matrix& rhs ) +{ + typedef TransExprTrait_ TT; + typedef CTransExprTrait_ CT; + typedef InvExprTrait_ IT; + + if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( IsSame::value && (~rhs).isAliased( this ) ) { + transpose(); + } + else if( IsSame::value && (~rhs).isAliased( this ) ) { + ctranspose(); + } + else if( !IsSame::value && (~rhs).canAlias( this ) ) { + const ResultType_ tmp( ~rhs ); + smpAssign( *this, tmp ); + } + else { + if( IsSparseMatrix::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& + CustomMatrix::operator+=( const Matrix& rhs ) +{ + if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& + CustomMatrix::operator-=( const Matrix& rhs ) +{ + if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& + CustomMatrix::operator*=( const Matrix& rhs ) +{ + if( m_ != n_ || (~rhs).rows() != m_ || (~rhs).columns() != n_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + const MultTrait_< ResultType, ResultType_ > 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_, CustomMatrix >& + CustomMatrix::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_, CustomMatrix >& + CustomMatrix::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::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::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::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::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::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::nonZeros() const +{ + size_t nonzeros( 0UL ); + + for( size_t j=0UL; j // Padding flag +inline size_t CustomMatrix::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 // Padding flag +inline void CustomMatrix::reset() +{ + using blaze::clear; + + for( size_t j=0UL; j // Padding flag +inline void CustomMatrix::reset( size_t j ) +{ + using blaze::clear; + + BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" ); + for( size_t i=0UL; i // Padding flag +inline void CustomMatrix::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& CustomMatrix::transpose() +{ + using std::swap; + + if( m_ != n_ ) { + BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" ); + } + + for( size_t j=1UL; j // Padding flag +inline CustomMatrix& CustomMatrix::ctranspose() +{ + if( m_ != n_ ) { + BLAZE_THROW_LOGIC_ERROR( "Impossible transpose operation" ); + } + + for( size_t j=0UL; j // Padding flag +template< typename Other > // Data type of the scalar value +inline CustomMatrix& CustomMatrix::scale( const Other& scalar ) +{ + for( size_t j=0UL; j // Padding flag +inline void CustomMatrix::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::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::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::reset( Type* ptr, size_t m, size_t n, Deleter d ) +{ + BLAZE_STATIC_ASSERT( !IsClass::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::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::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::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::SIMDType + CustomMatrix::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::SIMDType + CustomMatrix::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::SIMDType + CustomMatrix::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::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::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::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::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_::BLAZE_TEMPLATE VectorizedAssign > + CustomMatrix::assign( const DenseMatrix& 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 // Padding flag +template< typename MT > // Type of the right-hand side dense matrix +inline EnableIf_::BLAZE_TEMPLATE VectorizedAssign > + CustomMatrix::assign( const DenseMatrix& 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::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 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 // Padding flag +template< typename MT > // Type of the right-hand side dense matrix +inline void CustomMatrix::assign( const DenseMatrix& 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 // Padding flag +template< typename MT > // Type of the right-hand side sparse matrix +inline void CustomMatrix::assign( const SparseMatrix& 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_ 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::assign( const SparseMatrix& 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_ 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_::BLAZE_TEMPLATE VectorizedAddAssign > + CustomMatrix::addAssign( const DenseMatrix& 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::value ) + { + v_[j+j*mm_] += (~rhs)(j,j); + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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_::BLAZE_TEMPLATE VectorizedAddAssign > + CustomMatrix::addAssign( const DenseMatrix& 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::value ); + + for( size_t j=0UL; j::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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_ 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 // Padding flag +template< typename MT > // Type of the right-hand side dense matrix +inline void CustomMatrix::addAssign( const DenseMatrix& 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::value && ii < jj ) continue; + if( IsUpper::value && ii > jj ) break; + + for( size_t j=jj; j::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t iend ( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::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 // Padding flag +template< typename MT > // Type of the right-hand side sparse matrix +inline void CustomMatrix::addAssign( const SparseMatrix& 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_ 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::addAssign( const SparseMatrix& 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_ 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_::BLAZE_TEMPLATE VectorizedSubAssign > + CustomMatrix::subAssign( const DenseMatrix& 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::value ) + { + v_[j+j*mm_] -= (~rhs)(j,j); + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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_::BLAZE_TEMPLATE VectorizedSubAssign > + CustomMatrix::subAssign( const DenseMatrix& 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::value ); + + for( size_t j=0UL; j::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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_ 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 // Padding flag +template< typename MT > // Type of the right-hand side dense matrix +inline void CustomMatrix::subAssign( const DenseMatrix& 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::value && ii < jj ) continue; + if( IsUpper::value && ii > jj ) break; + + for( size_t j=jj; j::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t iend ( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::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 // Padding flag +template< typename MT > // Type of the right-hand side sparse matrix +inline void CustomMatrix::subAssign( const SparseMatrix& 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_ 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::subAssign( const SparseMatrix& 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_ 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& m ); + +template< typename Type, bool AF, bool PF, bool SO > +inline void reset( CustomMatrix& m, size_t i ); + +template< typename Type, bool AF, bool PF, bool SO > +inline void clear( CustomMatrix& m ); + +template< typename Type, bool AF, bool PF, bool SO > +inline bool isDefault( const CustomMatrix& m ); + +template< typename Type, bool AF, bool PF, bool SO > +inline bool isIntact( const CustomMatrix& m ); + +template< typename Type, bool AF, bool PF, bool SO > +inline void swap( CustomMatrix& a, CustomMatrix& 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& 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& 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& 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 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& 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 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& 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& a, CustomMatrix& b ) noexcept +{ + a.swap( b ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool AF, bool PF, bool SO > +struct HasConstDataAccess< CustomMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool AF, bool PF, bool SO > +struct HasMutableDataAccess< CustomMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISCUSTOM SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool AF, bool PF, bool SO > +struct IsCustom< CustomMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool PF, bool SO > +struct IsAligned< CustomMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool AF, bool SO > +struct IsPadded< CustomMatrix > : 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, StaticMatrix > +{ + using Type = StaticMatrix< AddTrait_, 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, StaticMatrix > +{ + using Type = StaticMatrix< AddTrait_, M, N, false >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2, bool AF, bool PF > +struct AddTrait< StaticMatrix, CustomMatrix > +{ + using Type = StaticMatrix< AddTrait_, 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, CustomMatrix > +{ + using Type = StaticMatrix< AddTrait_, M, N, false >; +}; + +template< typename T1, bool AF, bool PF, bool SO, typename T2, size_t M, size_t N > +struct AddTrait< CustomMatrix, HybridMatrix > +{ + using Type = HybridMatrix< AddTrait_, 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, HybridMatrix > +{ + using Type = HybridMatrix< AddTrait_, M, N, false >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2, bool AF, bool PF > +struct AddTrait< HybridMatrix, CustomMatrix > +{ + using Type = HybridMatrix< AddTrait_, 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, CustomMatrix > +{ + using Type = HybridMatrix< AddTrait_, M, N, false >; +}; + +template< typename T1, bool AF, bool PF, bool SO, typename T2 > +struct AddTrait< CustomMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< AddTrait_, SO >; +}; + +template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 > +struct AddTrait< CustomMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< AddTrait_, false >; +}; + +template< typename T1, bool SO, typename T2, bool AF, bool PF > +struct AddTrait< DynamicMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< AddTrait_, SO >; +}; + +template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 > +struct AddTrait< DynamicMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< AddTrait_, false >; +}; + +template< typename T1, bool AF1, bool PF1, bool SO, typename T2, bool AF2, bool PF2 > +struct AddTrait< CustomMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< AddTrait_, SO >; +}; + +template< typename T1, bool AF1, bool PF1, bool SO1, typename T2, bool AF2, bool PF2, bool SO2 > +struct AddTrait< CustomMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< AddTrait_, 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, StaticMatrix > +{ + using Type = StaticMatrix< SubTrait_, 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, StaticMatrix > +{ + using Type = StaticMatrix< SubTrait_, M, N, false >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2, bool AF, bool PF > +struct SubTrait< StaticMatrix, CustomMatrix > +{ + using Type = StaticMatrix< SubTrait_, 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, CustomMatrix > +{ + using Type = StaticMatrix< SubTrait_, M, N, false >; +}; + +template< typename T1, bool AF, bool PF, bool SO, typename T2, size_t M, size_t N > +struct SubTrait< CustomMatrix, HybridMatrix > +{ + using Type = HybridMatrix< SubTrait_, 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, HybridMatrix > +{ + using Type = HybridMatrix< SubTrait_, M, N, false >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2, bool AF, bool PF > +struct SubTrait< HybridMatrix, CustomMatrix > +{ + using Type = HybridMatrix< SubTrait_, 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, CustomMatrix > +{ + using Type = HybridMatrix< SubTrait_, M, N, false >; +}; + +template< typename T1, bool AF, bool PF, bool SO, typename T2 > +struct SubTrait< CustomMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< SubTrait_, SO >; +}; + +template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 > +struct SubTrait< CustomMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< SubTrait_, false >; +}; + +template< typename T1, bool SO, typename T2, bool AF, bool PF > +struct SubTrait< DynamicMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< SubTrait_, SO >; +}; + +template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 > +struct SubTrait< DynamicMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< SubTrait_, false >; +}; + +template< typename T1, bool AF1, bool PF1, bool SO, typename T2, bool AF2, bool PF2 > +struct SubTrait< CustomMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< SubTrait_, SO >; +}; + +template< typename T1, bool AF1, bool PF1, bool SO1, typename T2, bool AF2, bool PF2, bool SO2 > +struct SubTrait< CustomMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< SubTrait_, false >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool AF, bool PF, bool SO, typename T2 > +struct MultTrait< CustomMatrix, T2, EnableIf_ > > +{ + using Type = DynamicMatrix< MultTrait_, SO >; +}; + +template< typename T1, typename T2, bool AF, bool PF, bool SO > +struct MultTrait< T1, CustomMatrix, EnableIf_ > > +{ + using Type = DynamicMatrix< MultTrait_, SO >; +}; + +template< typename T1, bool AF, bool PF, bool SO, typename T2, size_t N > +struct MultTrait< CustomMatrix, StaticVector > +{ + using Type = DynamicVector< MultTrait_, false >; +}; + +template< typename T1, size_t N, typename T2, bool AF, bool PF, bool SO > +struct MultTrait< StaticVector, CustomMatrix > +{ + using Type = DynamicVector< MultTrait_, true >; +}; + +template< typename T1, bool AF, bool PF, bool SO, typename T2, size_t N > +struct MultTrait< CustomMatrix, HybridVector > +{ + using Type = DynamicVector< MultTrait_, false >; +}; + +template< typename T1, size_t N, typename T2, bool AF, bool PF, bool SO > +struct MultTrait< HybridVector, CustomMatrix > +{ + using Type = DynamicVector< MultTrait_, true >; +}; + +template< typename T1, bool AF, bool PF, bool SO, typename T2 > +struct MultTrait< CustomMatrix, DynamicVector > +{ + using Type = DynamicVector< MultTrait_, false >; +}; + +template< typename T1, typename T2, bool AF, bool PF, bool SO > +struct MultTrait< DynamicVector, CustomMatrix > +{ + using Type = DynamicVector< MultTrait_, true >; +}; + +template< typename T1, bool AF1, bool PF1, bool SO, typename T2, bool AF2, bool PF2 > +struct MultTrait< CustomMatrix, CustomVector > +{ + using Type = DynamicVector< MultTrait_, false >; +}; + +template< typename T1, bool AF1, bool PF1, typename T2, bool AF2, bool PF2, bool SO > +struct MultTrait< CustomVector, CustomMatrix > +{ + using Type = DynamicVector< MultTrait_, true >; +}; + +template< typename T1, bool AF, bool PF, bool SO, typename T2 > +struct MultTrait< CustomMatrix, CompressedVector > +{ + using Type = DynamicVector< MultTrait_, false >; +}; + +template< typename T1, typename T2, bool AF, bool PF, bool SO > +struct MultTrait< CompressedVector, CustomMatrix > +{ + using Type = DynamicVector< MultTrait_, true >; +}; + +template< typename T1, bool AF, bool PF, bool SO1, typename T2, size_t M, size_t N, bool SO2 > +struct MultTrait< CustomMatrix, StaticMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool AF, bool PF, bool SO2 > +struct MultTrait< StaticMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, bool AF, bool PF, bool SO1, typename T2, size_t M, size_t N, bool SO2 > +struct MultTrait< CustomMatrix, HybridMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool AF, bool PF, bool SO2 > +struct MultTrait< HybridMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 > +struct MultTrait< CustomMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 > +struct MultTrait< DynamicMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, bool AF1, bool PF1, bool SO1, typename T2, bool AF2, bool PF2, bool SO2 > +struct MultTrait< CustomMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool AF, bool PF, bool SO, typename T2 > +struct DivTrait< CustomMatrix, T2, EnableIf_ > > +{ + using Type = DynamicMatrix< DivTrait_, SO >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool AF, bool PF, bool SO > +struct SubmatrixTrait< CustomMatrix > +{ + using Type = DynamicMatrix; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool AF, bool PF, bool SO > +struct RowTrait< CustomMatrix > +{ + using Type = DynamicVector; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool AF, bool PF, bool SO > +struct ColumnTrait< CustomMatrix > +{ + using Type = DynamicVector; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 UnalignedUnpadded; + + // Definition of a custom column vector for unaligned but padded 'float' arrays + typedef CustomVector UnalignedPadded; + + // Definition of a custom row vector for aligned, unpadded 'double' arrays + typedef CustomVector AlignedUnpadded; + + // Definition of a custom row vector for aligned, padded 'complex' arrays + typedef CustomVector,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: +// +// -# \ref customvector_memory_management +// -# \ref customvector_copy_operations +// -# \ref customvector_alignment +// -# \ref customvector_padding +// +// \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 vec( 3UL ); + CustomVector 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 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 c( allocate( 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 CustomType; + + std::vector 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 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( 5UL ); // Needs to be 32-bit aligned + CustomVector 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 CustomType; + + // Creating padded custom vectors of size 3 and a capacity of 4 + CustomType a( allocate( 4UL ), 3UL, 4UL, Deallocate() ); + CustomType b( allocate( 4UL ), 3UL, 4UL, Deallocate() ); + CustomType c( allocate( 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 CustomType; + + // Creating unpadded custom vector of size 3 + CustomType a( allocate( 3UL ), 3UL, Deallocate() ); + CustomType b( allocate( 3UL ), 3UL, Deallocate() ); + CustomType c( allocate( 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 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 b( allocate( 4UL ), 2UL, 4UL, Deallocate() ); + + b = 2.0; // Homogeneous initialization of all elements + + CompressedVector c( 2 ); // Empty sparse single precision vector + DynamicVector d; // Default constructed dynamic vector + DynamicMatrix 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, TF > +{ + public: + //**Type definitions**************************************************************************** + typedef CustomVector This; //!< Type of this CustomVector instance. + typedef DenseVector BaseType; //!< Base type of this CustomVector instance. + typedef DynamicVector ResultType; //!< Result type for expression template evaluations. + typedef DynamicVector TransposeType; //!< Transpose type for expression template evaluations. + typedef Type ElementType; //!< Type of the vector elements. + typedef SIMDTrait_ 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 Iterator; //!< Iterator over non-constant elements. + typedef DenseIterator 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 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::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::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_ > > + 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 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& rhs ); + template< typename VT > inline CustomVector& operator+=( const Vector& rhs ); + template< typename VT > inline CustomVector& operator-=( const Vector& rhs ); + template< typename VT > inline CustomVector& operator*=( const Vector& rhs ); + template< typename VT > inline CustomVector& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_, CustomVector >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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_ > > + 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_ >::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_ >::value && + HasSIMDAdd< Type, ElementType_ >::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_ >::value && + HasSIMDSub< Type, ElementType_ >::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_ >::value && + HasSIMDMult< Type, ElementType_ >::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_ >::value && + HasSIMDDiv< Type, ElementType_ >::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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_ > assign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > assign( const DenseVector& rhs ); + + template< typename VT > inline void assign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > addAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > addAssign( const DenseVector& rhs ); + + template< typename VT > inline void addAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > subAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > subAssign( const DenseVector& rhs ); + + template< typename VT > inline void subAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > multAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > multAssign( const DenseVector& rhs ); + + template< typename VT > inline void multAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > divAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > divAssign( const DenseVector& rhs ); + //@} + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + size_t size_; //!< The size/dimension of the custom vector. + boost::shared_array 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::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::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::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::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::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::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::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::Reference + CustomVector::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::ConstReference + CustomVector::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::Reference + CustomVector::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::ConstReference + CustomVector::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::Pointer + CustomVector::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::ConstPointer + CustomVector::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::Iterator + CustomVector::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::ConstIterator + CustomVector::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::ConstIterator + CustomVector::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::Iterator + CustomVector::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::ConstIterator + CustomVector::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::ConstIterator + CustomVector::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& CustomVector::operator=( const Type& rhs ) +{ + for( size_t i=0UL; i 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& CustomVector::operator=( initializer_list 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 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& CustomVector::operator=( const Other (&array)[N] ) +{ + if( size_ != N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" ); + } + + for( size_t i=0UL; i // Transpose flag +inline CustomVector& CustomVector::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& + CustomVector::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& CustomVector::operator=( const Vector& rhs ) +{ + if( (~rhs).size() != size_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ tmp( ~rhs ); + smpAssign( *this, tmp ); + } + else { + if( IsSparseVector::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& CustomVector::operator+=( const Vector& rhs ) +{ + if( (~rhs).size() != size_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& CustomVector::operator-=( const Vector& rhs ) +{ + if( (~rhs).size() != size_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& CustomVector::operator*=( const Vector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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::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& + CustomVector::operator/=( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef DivTrait_< ResultType, ResultType_ > 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_, CustomVector >& + CustomVector::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_, CustomVector >& + CustomVector::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::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::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::nonZeros() const +{ + size_t nonzeros( 0 ); + + for( size_t i=0UL; i // Transpose flag +inline void CustomVector::reset() +{ + using blaze::clear; + for( size_t i=0UL; i // Transpose flag +inline void CustomVector::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& CustomVector::scale( const Other& scalar ) +{ + for( size_t i=0UL; i // Transpose flag +inline void CustomVector::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::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::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::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::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::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::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::SIMDType + CustomVector::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::SIMDType + CustomVector::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::SIMDType + CustomVector::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::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::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::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::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_::BLAZE_TEMPLATE VectorizedAssign > + CustomVector::assign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedAssign > + CustomVector::assign( const DenseVector& 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 it( (~rhs).begin() ); + + for( ; i // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void CustomVector::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedAddAssign > + CustomVector::addAssign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedAddAssign > + CustomVector::addAssign( const DenseVector& 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_ it( (~rhs).begin() ); + + for( ; i // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void CustomVector::addAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedSubAssign > + CustomVector::subAssign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedSubAssign > + CustomVector::subAssign( const DenseVector& 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_ it( (~rhs).begin() ); + + for( ; i // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void CustomVector::subAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedMultAssign > + CustomVector::multAssign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedMultAssign > + CustomVector::multAssign( const DenseVector& 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_ it( (~rhs).begin() ); + + for( ; i // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void CustomVector::multAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + const DynamicVector tmp( serial( *this ) ); + + reset(); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedDivAssign > + CustomVector::divAssign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedDivAssign > + CustomVector::divAssign( const DenseVector& 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_ it( (~rhs).begin() ); + + for( ; i // Transpose flag +class CustomVector + : public DenseVector< CustomVector, TF > +{ + public: + //**Type definitions**************************************************************************** + typedef CustomVector This; //!< Type of this CustomVector instance. + typedef DynamicVector ResultType; //!< Result type for expression template evaluations. + typedef DynamicVector TransposeType; //!< Transpose type for expression template evaluations. + typedef Type ElementType; //!< Type of the vector elements. + typedef SIMDTrait_ 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 Iterator; //!< Iterator over non-constant elements. + typedef DenseIterator 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 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::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::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 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& rhs ); + template< typename VT > inline CustomVector& operator+=( const Vector& rhs ); + template< typename VT > inline CustomVector& operator-=( const Vector& rhs ); + template< typename VT > inline CustomVector& operator*=( const Vector& rhs ); + template< typename VT > inline CustomVector& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_, CustomVector >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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_ >::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_ >::value && + HasSIMDAdd< Type, ElementType_ >::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_ >::value && + HasSIMDSub< Type, ElementType_ >::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_ >::value && + HasSIMDMult< Type, ElementType_ >::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_ >::value && + HasSIMDDiv< Type, ElementType_ >::value }; + }; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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_ > assign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > assign( const DenseVector& rhs ); + + template< typename VT > inline void assign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > addAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > addAssign( const DenseVector& rhs ); + + template< typename VT > inline void addAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > subAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > subAssign( const DenseVector& rhs ); + + template< typename VT > inline void subAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > multAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > multAssign( const DenseVector& rhs ); + + template< typename VT > inline void multAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > divAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > divAssign( const DenseVector& 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 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::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::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::value && capacity_ < nextMultiple( size_, SIMDSIZE ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Insufficient capacity for padded vector" ); + } + + v_.reset( ptr, NoDelete() ); + + if( IsVectorizable::value ) { + for( size_t i=size_; i // Transpose flag +template< typename Deleter > // Type of the custom deleter +inline CustomVector::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::value && capacity_ < nextMultiple( size_, SIMDSIZE ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Insufficient capacity for padded vector" ); + } + + v_.reset( ptr, d ); + + if( IsVectorizable::value ) { + for( size_t i=size_; i // Transpose flag +inline CustomVector::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::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::Reference + CustomVector::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::ConstReference + CustomVector::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::Reference + CustomVector::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::ConstReference + CustomVector::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::Pointer + CustomVector::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::ConstPointer + CustomVector::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::Iterator + CustomVector::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::ConstIterator + CustomVector::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::ConstIterator + CustomVector::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::Iterator + CustomVector::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::ConstIterator + CustomVector::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::ConstIterator + CustomVector::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& + CustomVector::operator=( const Type& rhs ) +{ + for( size_t i=0UL; i 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& + CustomVector::operator=( initializer_list 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 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& + CustomVector::operator=( const Other (&array)[N] ) +{ + if( size_ != N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid array size" ); + } + + for( size_t i=0UL; i // Transpose flag +inline CustomVector& + CustomVector::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& + CustomVector::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& + CustomVector::operator=( const Vector& rhs ) +{ + if( (~rhs).size() != size_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ tmp( ~rhs ); + smpAssign( *this, tmp ); + } + else { + if( IsSparseVector::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& + CustomVector::operator+=( const Vector& rhs ) +{ + if( (~rhs).size() != size_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& + CustomVector::operator-=( const Vector& rhs ) +{ + if( (~rhs).size() != size_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& + CustomVector::operator*=( const Vector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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::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& + CustomVector::operator/=( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT, TF ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef DivTrait_< ResultType, ResultType_ > 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_, CustomVector >& + CustomVector::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_, CustomVector >& + CustomVector::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::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::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::nonZeros() const +{ + size_t nonzeros( 0 ); + + for( size_t i=0UL; i // Transpose flag +inline void CustomVector::reset() +{ + using blaze::clear; + for( size_t i=0UL; i // Transpose flag +inline void CustomVector::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& + CustomVector::scale( const Other& scalar ) +{ + for( size_t i=0UL; i // Transpose flag +inline void CustomVector::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::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::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::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::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::SIMDType + CustomVector::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::SIMDType + CustomVector::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::SIMDType + CustomVector::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::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::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::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::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_::BLAZE_TEMPLATE VectorizedAssign > + CustomVector::assign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedAssign > + CustomVector::assign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::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 it( (~rhs).begin() ); + + for( ; i // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void CustomVector::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedAddAssign > + CustomVector::addAssign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedAddAssign > + CustomVector::addAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::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_ it( (~rhs).begin() ); + + for( ; i // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void CustomVector::addAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedSubAssign > + CustomVector::subAssign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedSubAssign > + CustomVector::subAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::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_ it( (~rhs).begin() ); + + for( ; i // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void CustomVector::subAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedMultAssign > + CustomVector::multAssign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedMultAssign > + CustomVector::multAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::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_ it( (~rhs).begin() ); + + for( ; i // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void CustomVector::multAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + const DynamicVector tmp( serial( *this ) ); + + reset(); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedDivAssign > + CustomVector::divAssign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedDivAssign > + CustomVector::divAssign( const DenseVector& 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_ it( (~rhs).begin() ); + + for( ; i +inline void reset( CustomVector& v ); + +template< typename Type, bool AF, bool PF, bool TF > +inline void clear( CustomVector& v ); + +template< typename Type, bool AF, bool PF, bool TF > +inline bool isDefault( const CustomVector& v ); + +template< typename Type, bool AF, bool PF, bool TF > +inline bool isIntact( const CustomVector& v ) noexcept; + +template< typename Type, bool AF, bool PF, bool TF > +inline void swap( CustomVector& a, CustomVector& 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& 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& 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 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& 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 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& 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& a, CustomVector& b ) noexcept +{ + a.swap( b ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool AF, bool PF, bool TF > +struct HasConstDataAccess< CustomVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool AF, bool PF, bool TF > +struct HasMutableDataAccess< CustomVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISCUSTOM SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool AF, bool PF, bool TF > +struct IsCustom< CustomVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool PF, bool TF > +struct IsAligned< CustomVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool AF, bool TF > +struct IsPadded< CustomVector > : 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, StaticVector > +{ + using Type = StaticVector< AddTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF > +struct AddTrait< StaticVector, CustomVector > +{ + using Type = StaticVector< AddTrait_, N, TF >; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N > +struct AddTrait< CustomVector, HybridVector > +{ + using Type = HybridVector< AddTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF > +struct AddTrait< HybridVector, CustomVector > +{ + using Type = HybridVector< AddTrait_, N, TF >; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2 > +struct AddTrait< CustomVector, DynamicVector > +{ + using Type = DynamicVector< AddTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2, bool AF, bool PF > +struct AddTrait< DynamicVector, CustomVector > +{ + using Type = DynamicVector< AddTrait_, TF >; +}; + +template< typename T1, bool AF1, bool PF1, bool TF, typename T2, bool AF2, bool PF2 > +struct AddTrait< CustomVector, CustomVector > +{ + using Type = DynamicVector< AddTrait_, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N > +struct SubTrait< CustomVector, StaticVector > +{ + using Type = StaticVector< SubTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF > +struct SubTrait< StaticVector, CustomVector > +{ + using Type = StaticVector< SubTrait_, N, TF >; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N > +struct SubTrait< CustomVector, HybridVector > +{ + using Type = HybridVector< SubTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF > +struct SubTrait< HybridVector, CustomVector > +{ + using Type = HybridVector< SubTrait_, N, TF >; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2 > +struct SubTrait< CustomVector, DynamicVector > +{ + using Type = DynamicVector< SubTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2, bool AF, bool PF > +struct SubTrait< DynamicVector, CustomVector > +{ + using Type = DynamicVector< SubTrait_, TF >; +}; + +template< typename T1, bool AF1, bool PF1, bool TF, typename T2, bool AF2, bool PF2 > +struct SubTrait< CustomVector, CustomVector > +{ + using Type = DynamicVector< SubTrait_, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool AF, bool PF, bool TF, typename T2 > +struct MultTrait< CustomVector, T2, EnableIf_ > > +{ + using Type = DynamicVector< MultTrait_, TF >; +}; + +template< typename T1, typename T2, bool AF, bool PF, bool TF > +struct MultTrait< T1, CustomVector, EnableIf_ > > +{ + using Type = DynamicVector< MultTrait_, TF >; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N > +struct MultTrait< CustomVector, StaticVector > +{ + using Type = StaticVector< MultTrait_, N, TF >; +}; + +template< typename T1, bool AF, bool PF, typename T2, size_t N > +struct MultTrait< CustomVector, StaticVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, bool AF, bool PF, typename T2, size_t N > +struct MultTrait< CustomVector, StaticVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF > +struct MultTrait< StaticVector, CustomVector > +{ + using Type = StaticVector< MultTrait_, N, TF >; +}; + +template< typename T1, size_t N, typename T2, bool AF, bool PF > +struct MultTrait< StaticVector, CustomVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, size_t N, typename T2, bool AF, bool PF > +struct MultTrait< StaticVector, CustomVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N > +struct MultTrait< CustomVector, HybridVector > +{ + using Type = HybridVector< MultTrait_, N, TF >; +}; + +template< typename T1, bool AF, bool PF, typename T2, size_t N > +struct MultTrait< CustomVector, HybridVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, bool AF, bool PF, typename T2, size_t N > +struct MultTrait< CustomVector, HybridVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF > +struct MultTrait< HybridVector, CustomVector > +{ + using Type = HybridVector< MultTrait_, N, TF >; +}; + +template< typename T1, size_t N, typename T2, bool AF, bool PF > +struct MultTrait< HybridVector, CustomVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, size_t N, typename T2, bool AF, bool PF > +struct MultTrait< HybridVector, CustomVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2 > +struct MultTrait< CustomVector, DynamicVector > +{ + using Type = DynamicVector< MultTrait_, TF >; +}; + +template< typename T1, bool AF, bool PF, typename T2 > +struct MultTrait< CustomVector, DynamicVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, bool AF, bool PF, typename T2 > +struct MultTrait< CustomVector, DynamicVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, bool TF, typename T2, bool AF, bool PF > +struct MultTrait< DynamicVector, CustomVector > +{ + using Type = DynamicVector< MultTrait_, TF >; +}; + +template< typename T1, typename T2, bool AF, bool PF > +struct MultTrait< DynamicVector, CustomVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, typename T2, bool AF, bool PF > +struct MultTrait< DynamicVector, CustomVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, bool AF1, bool PF1, bool TF, typename T2, bool AF2, bool PF2 > +struct MultTrait< CustomVector, CustomVector > +{ + using Type = DynamicVector< MultTrait_, TF >; +}; + +template< typename T1, bool AF1, bool PF1, typename T2, bool AF2, bool PF2 > +struct MultTrait< CustomVector, CustomVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, bool AF1, bool PF1, typename T2, bool AF2, bool PF2 > +struct MultTrait< CustomVector, CustomVector > +{ + using Type = MultTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// CROSSTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool AF, bool PF, bool TF, typename T2 > +struct CrossTrait< CustomVector, StaticVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, bool TF, typename T2, bool AF, bool PF > +struct CrossTrait< StaticVector, CustomVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N > +struct CrossTrait< CustomVector, HybridVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF > +struct CrossTrait< HybridVector, CustomVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2 > +struct CrossTrait< CustomVector, DynamicVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, bool TF, typename T2, bool AF, bool PF > +struct CrossTrait< DynamicVector, CustomVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, bool AF1, bool PF1, bool TF, typename T2, bool AF2, bool PF2 > +struct CrossTrait< CustomVector, CustomVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool AF, bool PF, bool TF, typename T2 > +struct DivTrait< CustomVector, T2, EnableIf_ > > +{ + using Type = DynamicVector< DivTrait_, TF >; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N > +struct DivTrait< CustomVector, StaticVector > +{ + using Type = StaticVector< DivTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF > +struct DivTrait< StaticVector, CustomVector > +{ + using Type = StaticVector< DivTrait_, N, TF >; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2, size_t N > +struct DivTrait< CustomVector, HybridVector > +{ + using Type = HybridVector< DivTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2, bool AF, bool PF > +struct DivTrait< HybridVector, CustomVector > +{ + using Type = HybridVector< DivTrait_, N, TF >; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2 > +struct DivTrait< CustomVector, DynamicVector > +{ + using Type = DynamicVector< DivTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2, bool AF, bool PF > +struct DivTrait< DynamicVector, CustomVector > +{ + using Type = DynamicVector< DivTrait_, TF >; +}; + +template< typename T1, bool AF1, bool PF1, bool TF, typename T2, bool AF2, bool PF2 > +struct DivTrait< CustomVector, CustomVector > +{ + using Type = DynamicVector< DivTrait_, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTORTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool AF, bool PF, bool TF > +struct SubvectorTrait< CustomVector > +{ + using Type = DynamicVector; +}; +/*! \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 +#include +#include +#include +#include + + +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_ SIMDType; + //********************************************************************************************** + + //**Constructors******************************************************************************** + /*!\name Constructors */ + //@{ + explicit inline DenseIterator() noexcept; + explicit inline DenseIterator( Type* ptr ) noexcept; + + template< typename Other, bool AF2 > + inline DenseIterator( const DenseIterator& 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::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::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::DenseIterator( const DenseIterator& 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& DenseIterator::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& DenseIterator::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& DenseIterator::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 DenseIterator::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& DenseIterator::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 DenseIterator::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::ReferenceType + DenseIterator::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::ReferenceType + DenseIterator::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::PointerType + DenseIterator::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::PointerType DenseIterator::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::SIMDType + DenseIterator::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::SIMDType + DenseIterator::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::SIMDType + DenseIterator::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::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::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::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::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& lhs, const DenseIterator& rhs ) noexcept; + +template< typename T1, bool AF1, typename T2, bool AF2 > +inline bool operator!=( const DenseIterator& lhs, const DenseIterator& rhs ) noexcept; + +template< typename T1, bool AF1, typename T2, bool AF2 > +inline bool operator<( const DenseIterator& lhs, const DenseIterator& rhs ) noexcept; + +template< typename T1, bool AF1, typename T2, bool AF2 > +inline bool operator>( const DenseIterator& lhs, const DenseIterator& rhs ) noexcept; + +template< typename T1, bool AF1, typename T2, bool AF2 > +inline bool operator<=( const DenseIterator& lhs, const DenseIterator& rhs ) noexcept; + +template< typename T1, bool AF1, typename T2, bool AF2 > +inline bool operator>=( const DenseIterator& lhs, const DenseIterator& rhs ) noexcept; + +template< typename Type, bool AF > +inline const DenseIterator operator+( const DenseIterator& it, ptrdiff_t inc ) noexcept; + +template< typename Type, bool AF > +inline const DenseIterator operator+( ptrdiff_t inc, const DenseIterator& it ) noexcept; + +template< typename Type, bool AF > +inline const DenseIterator operator-( const DenseIterator& it, ptrdiff_t inc ) noexcept; + +template< typename Type, bool AF > +inline ptrdiff_t operator-( const DenseIterator& lhs, const DenseIterator& 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& lhs, const DenseIterator& 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& lhs, const DenseIterator& 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& lhs, const DenseIterator& 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& lhs, const DenseIterator& 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& lhs, const DenseIterator& 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& lhs, const DenseIterator& 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 operator+( const DenseIterator& it, ptrdiff_t inc ) noexcept +{ + return DenseIterator( 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 operator+( ptrdiff_t inc, const DenseIterator& it ) noexcept +{ + return DenseIterator( 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 operator-( const DenseIterator& it, ptrdiff_t dec ) noexcept +{ + return DenseIterator( 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& lhs, const DenseIterator& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name DenseMatrix operators */ +//@{ +template< typename T1, typename T2 > +inline bool operator==( const DenseMatrix& lhs, const DenseMatrix& rhs ); + +template< typename T1, typename T2 > +inline bool operator==( const DenseMatrix& lhs, const DenseMatrix& rhs ); + +template< typename T1, typename T2, bool SO > +inline bool operator==( const DenseMatrix& lhs, const DenseMatrix& rhs ); + +template< typename T1, typename T2, bool SO > +inline bool operator==( const DenseMatrix& lhs, const SparseMatrix& rhs ); + +template< typename T1, typename T2, bool SO > +inline bool operator==( const DenseMatrix& lhs, const SparseMatrix& rhs ); + +template< typename T1, bool SO1, typename T2, bool SO2 > +inline bool operator==( const SparseMatrix& lhs, const DenseMatrix& rhs ); + +template< typename T1, typename T2 > +inline EnableIf_, bool > operator==( const DenseMatrix& mat, T2 scalar ); + +template< typename T1, typename T2 > +inline EnableIf_, bool > operator==( const DenseMatrix& mat, T2 scalar ); + +template< typename T1, typename T2, bool SO > +inline EnableIf_, bool > operator==( T1 scalar, const DenseMatrix& mat ); + +template< typename T1, bool SO1, typename T2, bool SO2 > +inline bool operator!=( const DenseMatrix& lhs, const DenseMatrix& rhs ); + +template< typename T1, bool SO1, typename T2, bool SO2 > +inline bool operator!=( const DenseMatrix& lhs, const SparseMatrix& rhs ); + +template< typename T1, bool SO1, typename T2, bool SO2 > +inline bool operator!=( const SparseMatrix& lhs, const DenseMatrix& rhs ); + +template< typename T1, typename T2, bool SO > +inline EnableIf_, bool > operator!=( const DenseMatrix& mat, T2 scalar ); + +template< typename T1, typename T2, bool SO > +inline EnableIf_, bool > operator!=( T1 scalar, const DenseMatrix& 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& lhs, const DenseMatrix& rhs ) +{ + typedef CompositeType_ CT1; + typedef CompositeType_ 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 // Type of the right-hand side dense matrix +inline bool operator==( const DenseMatrix& lhs, const DenseMatrix& rhs ) +{ + typedef CompositeType_ CT1; + typedef CompositeType_ 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 // Storage order +inline bool operator==( const DenseMatrix& lhs, const DenseMatrix& rhs ) +{ + typedef CompositeType_ CT1; + typedef CompositeType_ 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 // Storage order of the left-hand side dense matrix +inline bool operator==( const DenseMatrix& lhs, const SparseMatrix& rhs ) +{ + typedef CompositeType_ CT1; + typedef CompositeType_ CT2; + typedef ConstIterator_< RemoveReference_ > 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; iindex(); ++j ) { + if( !isDefault( A(i,j) ) ) return false; + } + if( !equal( element->value(), A(i,j) ) ) return false; + } + for( ; j // Storage order of the left-hand side dense matrix +inline bool operator==( const DenseMatrix& lhs, const SparseMatrix& rhs ) +{ + typedef CompositeType_ CT1; + typedef CompositeType_ CT2; + typedef ConstIterator_< RemoveReference_ > 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; jindex(); ++i ) { + if( !isDefault( A(i,j) ) ) return false; + } + if( !equal( element->value(), A(i,j) ) ) return false; + } + for( ; i // Storage order of the right-hand side sparse matrix +inline bool operator==( const SparseMatrix& lhs, const DenseMatrix& 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_, bool > operator==( const DenseMatrix& mat, T2 scalar ) +{ + typedef CompositeType_ 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 // Type of the right-hand side scalar +inline EnableIf_, bool > operator==( const DenseMatrix& mat, T2 scalar ) +{ + typedef CompositeType_ 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 // Storage order +inline EnableIf_, bool > operator==( T1 scalar, const DenseMatrix& 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& lhs, const DenseMatrix& 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& lhs, const SparseMatrix& 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& lhs, const DenseMatrix& 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_, bool > operator!=( const DenseMatrix& 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_, bool > operator!=( T1 scalar, const DenseMatrix& mat ) +{ + return !( mat == scalar ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name DenseMatrix functions */ +//@{ +template< typename MT, bool SO > +bool isnan( const DenseMatrix& dm ); + +template< typename MT, bool SO > +bool isSymmetric( const DenseMatrix& dm ); + +template< typename MT, bool SO > +bool isHermitian( const DenseMatrix& dm ); + +template< typename MT, bool SO > +bool isUniform( const DenseMatrix& dm ); + +template< typename MT, bool SO > +bool isLower( const DenseMatrix& dm ); + +template< typename MT, bool SO > +bool isUniLower( const DenseMatrix& dm ); + +template< typename MT, bool SO > +bool isStrictlyLower( const DenseMatrix& dm ); + +template< typename MT, bool SO > +bool isUpper( const DenseMatrix& dm ); + +template< typename MT, bool SO > +bool isUniUpper( const DenseMatrix& dm ); + +template< typename MT, bool SO > +bool isStrictlyUpper( const DenseMatrix& dm ); + +template< typename MT, bool SO > +bool isDiagonal( const DenseMatrix& dm ); + +template< typename MT, bool SO > +bool isIdentity( const DenseMatrix& dm ); + +template< typename MT, bool SO > +const ElementType_ min( const DenseMatrix& dm ); + +template< typename MT, bool SO > +const ElementType_ max( const DenseMatrix& 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 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& dm ) +{ + typedef CompositeType_ CT; + + CT A( ~dm ); // Evaluation of the dense matrix operand + + if( SO == rowMajor ) { + for( size_t i=0UL; i 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& dm ) +{ + typedef CompositeType_ CT; + + if( IsSymmetric::value ) + return true; + + if( !isSquare( ~dm ) ) + return false; + + if( (~dm).rows() < 2UL ) + return true; + + if( IsTriangular::value ) + return isDiagonal( ~dm ); + + CT A( ~dm ); // Evaluation of the dense matrix operand + + if( SO == rowMajor ) { + for( size_t i=1UL; i 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& dm ) +{ + typedef ElementType_ ET; + typedef CompositeType_ CT; + + if( IsHermitian::value ) + return true; + + if( !IsNumeric::value || !isSquare( ~dm ) ) + return false; + + if( (~dm).rows() < 2UL ) + return true; + + if( IsTriangular::value ) + return isDiagonal( ~dm ); + + CT A( ~dm ); // Evaluation of the dense matrix operand + + if( SO == rowMajor ) { + for( size_t i=0UL; i // Type of the dense matrix +bool isUniform_backend( const DenseMatrix& 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::value )?( 1UL ):( 0UL ) ); + const size_t iend ( ( IsStrictlyUpper::value )?( (~dm).rows()-1UL ):( (~dm).rows() ) ); + + for( size_t i=ibegin; i::value ) { + for( size_t j=0UL; j::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& 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::value )?( 1UL ):( 0UL ) ); + const size_t jend ( ( IsStrictlyLower::value )?( (~dm).columns()-1UL ):( (~dm).columns() ) ); + + for( size_t j=jbegin; j::value ) { + for( size_t i=0UL; i::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& 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_ 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& 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_ 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 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& dm ) +{ + if( IsUniTriangular::value ) + return false; + + if( (~dm).rows() == 0UL || (~dm).columns() == 0UL || + ( (~dm).rows() == 1UL && (~dm).columns() == 1UL ) ) + return true; + + CompositeType_ A( ~dm ); // Evaluation of the dense matrix operand + + return isUniform_backend( A, typename IsTriangular::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 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& dm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + + if( IsLower::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, 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& dm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + + if( IsUniLower::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, 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& dm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + + if( IsStrictlyLower::value ) + return true; + + if( IsUniLower::value || IsUniUpper::value || !isSquare( ~dm ) ) + return false; + + Tmp A( ~dm ); // Evaluation of the dense matrix operand + + if( SO == rowMajor ) { + for( size_t i=0UL; i 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& dm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + + if( IsUpper::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, 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& dm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + + if( IsUniUpper::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, 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& dm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + + if( IsStrictlyUpper::value ) + return true; + + if( IsUniLower::value || IsUniUpper::value || !isSquare( ~dm ) ) + return false; + + Tmp A( ~dm ); // Evaluation of the dense matrix operand + + if( SO == rowMajor ) { + for( size_t i=0UL; i 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& dm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + + if( IsDiagonal::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::value ) { + for( size_t j=0UL; j::value ) { + for( size_t j=i+1UL; j::value ) { + for( size_t i=0UL; i::value ) { + for( size_t i=j+1UL; i 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& dm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + + if( IsIdentity::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::value ) { + for( size_t j=0UL; j::value && !IsUniUpper::value && !isOne( A(i,i) ) ) { + return false; + } + if( !IsLower::value ) { + for( size_t j=i+1UL; j::value ) { + for( size_t i=0UL; i::value && !IsUniUpper::value && !isOne( A(j,j) ) ) { + return false; + } + if( !IsUpper::value ) { + for( size_t i=j+1UL; i // Storage order +const ElementType_ min( const DenseMatrix& dm ) +{ + using blaze::min; + + typedef ElementType_ ET; + typedef CompositeType_ 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 // Transpose flag +const ElementType_ max( const DenseMatrix& dm ) +{ + using blaze::max; + + typedef ElementType_ ET; + typedef CompositeType_ 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name DenseVector operators */ +//@{ +template< typename T1, bool TF1, typename T2, bool TF2 > +inline bool operator==( const DenseVector& lhs, const DenseVector& rhs ); + +template< typename T1, bool TF1, typename T2, bool TF2 > +inline bool operator==( const DenseVector& lhs, const SparseVector& rhs ); + +template< typename T1, bool TF1, typename T2, bool TF2 > +inline bool operator==( const SparseVector& lhs, const DenseVector& rhs ); + +template< typename T1, typename T2, bool TF > +inline EnableIf_, bool > operator==( const DenseVector& vec, T2 scalar ); + +template< typename T1, typename T2, bool TF > +inline EnableIf_, bool > operator==( T1 scalar, const DenseVector& vec ); + +template< typename T1, bool TF1, typename T2, bool TF2 > +inline bool operator!=( const DenseVector& lhs, const DenseVector& rhs ); + +template< typename T1, bool TF1, typename T2, bool TF2 > +inline bool operator!=( const DenseVector& lhs, const SparseVector& rhs ); + +template< typename T1, bool TF1, typename T2, bool TF2 > +inline bool operator!=( const SparseVector& lhs, const DenseVector& rhs ); + +template< typename T1, typename T2, bool TF > +inline EnableIf_, bool > operator!=( const DenseVector& vec, T2 scalar ); + +template< typename T1, typename T2, bool TF > +inline EnableIf_, bool > operator!=( T1 scalar, const DenseVector& 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& lhs, const DenseVector& rhs ) +{ + typedef CompositeType_ CT1; + typedef CompositeType_ 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 // Transpose flag of the right-hand side sparse vector +inline bool operator==( const DenseVector& lhs, const SparseVector& rhs ) +{ + typedef CompositeType_ CT1; + typedef CompositeType_ CT2; + typedef ConstIterator_< RemoveReference_ > 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( ; iindex(); ++i ) { + if( !isDefault( a[i] ) ) return false; + } + if( !equal( element->value(), a[i] ) ) return false; + } + for( ; i // Transpose flag of the right-hand side dense vector +inline bool operator==( const SparseVector& lhs, const DenseVector& 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_, bool > operator==( const DenseVector& vec, T2 scalar ) +{ + typedef CompositeType_ 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 // Transpose flag +inline EnableIf_, bool > operator==( T1 scalar, const DenseVector& 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& lhs, const DenseVector& 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& lhs, const SparseVector& 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& lhs, const DenseVector& 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_, bool > operator!=( const DenseVector& 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_, bool > operator!=( T1 scalar, const DenseVector& vec ) +{ + return !( vec == scalar ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name DenseVector functions */ +//@{ +template< typename VT, bool TF > +bool isnan( const DenseVector& dv ); + +template< typename VT, bool TF > +bool isDivisor( const DenseVector& dv ); + +template< typename VT, bool TF > +bool isUniform( const DenseVector& dv ); + +template< typename VT, bool TF > +const ElementType_ sqrLength( const DenseVector& dv ); + +template< typename VT, bool TF > +inline auto length( const DenseVector& dv ) -> decltype( sqrt( sqrLength( ~dv ) ) ); + +template< typename VT, bool TF > +const ElementType_ min( const DenseVector& dv ); + +template< typename VT, bool TF > +const ElementType_ max( const DenseVector& 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 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& dv ) +{ + CompositeType_ a( ~dv ); // Evaluation of the dense vector operand + + for( size_t i=0UL; i a{ 1, -1, 2 }; // isDivisor( a ) returns true + StaticVector 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& dv ) +{ + CompositeType_ a( ~dv ); // Evaluation of the dense vector operand + + for( size_t i=0UL; i 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& dv ) +{ + typedef CompositeType_ CT; + typedef ConstReference_< RemoveReference_ > 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_ sqrLength( const DenseVector& dv ) +{ + typedef ElementType_ 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: +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +//
\b Type \b LengthType
floatfloat
integral data types and doubledouble
long doublelong double
complexcomplex
+// +// \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& 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_ min( const DenseVector& dv ) +{ + using blaze::min; + + typedef ElementType_ ET; + typedef CompositeType_ 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 // Transpose flag +const ElementType_ max( const DenseVector& dv ) +{ + using blaze::max; + + typedef ElementType_ ET; + typedef CompositeType_ 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 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 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 C( 2, 3 ); // Empty row-major sparse single precision matrix + DynamicMatrix D( 3, 2, 4.0F ); // Directly, homogeneously initialized single precision 3x2 matrix + + DynamicMatrix E( A ); // Creation of a new row-major matrix as a copy of A + DynamicMatrix 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, SO > +{ + public: + //**Type definitions**************************************************************************** + typedef DynamicMatrix This; //!< Type of this DynamicMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this DynamicMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef DynamicMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef DynamicMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef Type ElementType; //!< Type of the matrix elements. + typedef SIMDTrait_ 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 Iterator; //!< Iterator over non-constant elements. + typedef DenseIterator 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 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::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::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 > 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& 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 > 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& rhs ); + template< typename MT, bool SO2 > inline DynamicMatrix& operator+=( const Matrix& rhs ); + template< typename MT, bool SO2 > inline DynamicMatrix& operator-=( const Matrix& rhs ); + template< typename MT, bool SO2 > inline DynamicMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_, DynamicMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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_ >::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_ >::value && + HasSIMDAdd< Type, ElementType_ >::value && + !IsDiagonal::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_ >::value && + HasSIMDSub< Type, ElementType_ >::value && + !IsDiagonal::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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_ > assign( const DenseMatrix& rhs ); + + template< typename MT > + inline EnableIf_ > assign( const DenseMatrix& rhs ); + + template< typename MT > inline void assign( const DenseMatrix& rhs ); + template< typename MT > inline void assign( const SparseMatrix& rhs ); + template< typename MT > inline void assign( const SparseMatrix& rhs ); + + template< typename MT > + inline DisableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT > + inline EnableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT > inline void addAssign( const DenseMatrix& rhs ); + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + + template< typename MT > + inline DisableIf_ > subAssign( const DenseMatrix& rhs ); + + template< typename MT > + inline EnableIf_ > subAssign( const DenseMatrix& rhs ); + + template< typename MT > inline void subAssign( const DenseMatrix& rhs ); + template< typename MT > inline void subAssign( const SparseMatrix& rhs ); + template< typename MT > inline void subAssign( const SparseMatrix& 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::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::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( capacity_ ) ) // The matrix elements +{ + if( IsVectorizable::value ) { + for( size_t i=0UL; i // Storage order +inline DynamicMatrix::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( capacity_ ) ) // The matrix elements +{ + for( size_t i=0UL; i::value ) { + for( size_t j=n_; j 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::DynamicMatrix( initializer_list< initializer_list > 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( 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 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::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( capacity_ ) ) // The matrix elements +{ + for( size_t i=0UL; i::value ) { + for( size_t j=n; j 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::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( capacity_ ) ) // The matrix elements +{ + for( size_t i=0UL; i::value ) { + for( size_t j=N; j // Storage order +inline DynamicMatrix::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( capacity_ ) ) // The matrix elements +{ + BLAZE_INTERNAL_ASSERT( capacity_ <= m.capacity_, "Invalid capacity estimation" ); + + for( size_t i=0UL; i // Storage order +inline DynamicMatrix::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::DynamicMatrix( const Matrix& 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( capacity_ ) ) // The matrix elements +{ + for( size_t i=0UL; i::value ? 0UL : n_ ); + j<( IsVectorizable::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::~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::Reference + DynamicMatrix::operator()( size_t i, size_t j ) noexcept +{ + BLAZE_USER_ASSERT( i // Storage order +inline typename DynamicMatrix::ConstReference + DynamicMatrix::operator()( size_t i, size_t j ) const noexcept +{ + BLAZE_USER_ASSERT( i // Storage order +inline typename DynamicMatrix::Reference + DynamicMatrix::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::ConstReference + DynamicMatrix::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::Pointer + DynamicMatrix::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::ConstPointer + DynamicMatrix::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::Pointer + DynamicMatrix::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::ConstPointer + DynamicMatrix::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::Iterator + DynamicMatrix::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::ConstIterator + DynamicMatrix::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::ConstIterator + DynamicMatrix::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::Iterator + DynamicMatrix::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::ConstIterator + DynamicMatrix::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::ConstIterator + DynamicMatrix::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& DynamicMatrix::operator=( const Type& rhs ) +{ + for( size_t i=0UL; i 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& + DynamicMatrix::operator=( initializer_list< initializer_list > 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 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& DynamicMatrix::operator=( const Other (&array)[M][N] ) +{ + resize( M, N, false ); + + for( size_t i=0UL; i // Storage order +inline DynamicMatrix& DynamicMatrix::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& DynamicMatrix::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& DynamicMatrix::operator=( const Matrix& rhs ) +{ + typedef TransExprTrait_ TT; + typedef CTransExprTrait_ CT; + typedef InvExprTrait_ IT; + + if( IsSame::value && (~rhs).isAliased( this ) ) { + transpose(); + } + else if( IsSame::value && (~rhs).isAliased( this ) ) { + ctranspose(); + } + else if( !IsSame::value && (~rhs).canAlias( this ) ) { + DynamicMatrix tmp( ~rhs ); + swap( tmp ); + } + else { + resize( (~rhs).rows(), (~rhs).columns(), false ); + if( IsSparseMatrix::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& DynamicMatrix::operator+=( const Matrix& rhs ) +{ + if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& DynamicMatrix::operator-=( const Matrix& rhs ) +{ + if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& DynamicMatrix::operator*=( const Matrix& 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_, DynamicMatrix >& + DynamicMatrix::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_, DynamicMatrix >& + DynamicMatrix::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::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::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::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::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::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::nonZeros() const +{ + size_t nonzeros( 0UL ); + + for( size_t i=0UL; i // Storage order +inline size_t DynamicMatrix::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 // Storage order +inline void DynamicMatrix::reset() +{ + using blaze::clear; + + for( size_t i=0UL; i // Storage order +inline void DynamicMatrix::reset( size_t i ) +{ + using blaze::clear; + + BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" ); + for( size_t j=0UL; j // Storage order +inline void DynamicMatrix::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::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( m*nn ); + const size_t min_m( min( m, m_ ) ); + const size_t min_n( min( n, n_ ) ); + + for( size_t i=0UL; i capacity_ ) { + Type* BLAZE_RESTRICT v = allocate( m*nn ); + std::swap( v_, v ); + deallocate( v ); + capacity_ = m*nn; + } + + if( IsVectorizable::value ) { + for( size_t i=0UL; i // Storage order +inline void DynamicMatrix::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::reserve( size_t elements ) +{ + if( elements > capacity_ ) + { + // Allocating a new array + Type* BLAZE_RESTRICT tmp = allocate( elements ); + + // Initializing the new array + transfer( v_, v_+capacity_, tmp ); + + if( IsVectorizable::value ) { + for( size_t i=capacity_; i // Storage order +inline DynamicMatrix& DynamicMatrix::transpose() +{ + using std::swap; + + const size_t block( BLOCK_SIZE ); + + if( m_ == n_ ) + { + for( size_t ii=0UL; iiswap( 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& DynamicMatrix::ctranspose() +{ + const size_t block( BLOCK_SIZE ); + + if( m_ == n_ ) + { + for( size_t ii=0UL; ii // Storage order +template< typename Other > // Data type of the scalar value +inline DynamicMatrix& DynamicMatrix::scale( const Other& scalar ) +{ + for( size_t i=0UL; i // Storage order +inline void DynamicMatrix::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::adjustColumns( size_t minColumns ) const noexcept +{ + if( usePadding && IsVectorizable::value ) + return nextMultiple( 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::isIntact() const noexcept +{ + if( m_ * n_ > capacity_ ) + return false; + + if( IsVectorizable::value ) { + for( size_t i=0UL; i // Storage order +template< typename Other > // Data type of the foreign expression +inline bool DynamicMatrix::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::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::SIMDType + DynamicMatrix::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::SIMDType + DynamicMatrix::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::SIMDType + DynamicMatrix::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::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::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::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::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_::BLAZE_TEMPLATE VectorizedAssign > + DynamicMatrix::assign( const DenseMatrix& 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 // Storage order +template< typename MT > // Type of the right-hand side dense matrix +inline EnableIf_::BLAZE_TEMPLATE VectorizedAssign > + DynamicMatrix::assign( const DenseMatrix& 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::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 right( (~rhs).begin(i) ); + + for( ; j 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 // Storage order +template< typename MT > // Type of the right-hand side dense matrix +inline void DynamicMatrix::assign( const DenseMatrix& 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 // Storage order +template< typename MT > // Type of the right-hand side sparse matrix +inline void DynamicMatrix::assign( const SparseMatrix& 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 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::assign( const SparseMatrix& 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 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_::BLAZE_TEMPLATE VectorizedAddAssign > + DynamicMatrix::addAssign( const DenseMatrix& 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::value ) + { + v_[i*nn_+i] += (~rhs)(i,i); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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_::BLAZE_TEMPLATE VectorizedAddAssign > + DynamicMatrix::addAssign( const DenseMatrix& 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::value ); + + for( size_t i=0UL; i::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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_ 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 // Storage order +template< typename MT > // Type of the right-hand side dense matrix +inline void DynamicMatrix::addAssign( const DenseMatrix& 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::value && ii < jj ) break; + if( IsUpper::value && ii > jj ) continue; + + for( size_t i=ii; i::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jend ( ( IsLower::value ) + ?( min( ( IsStrictlyLower::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 // Storage order +template< typename MT > // Type of the right-hand side sparse matrix +inline void DynamicMatrix::addAssign( const SparseMatrix& 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 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::addAssign( const SparseMatrix& 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 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_::BLAZE_TEMPLATE VectorizedSubAssign > + DynamicMatrix::subAssign( const DenseMatrix& 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::value ) + { + v_[i*nn_+i] -= (~rhs)(i,i); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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_::BLAZE_TEMPLATE VectorizedSubAssign > + DynamicMatrix::subAssign( const DenseMatrix& 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::value ); + + for( size_t i=0UL; i::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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_ 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 // Storage order +template< typename MT > // Type of the right-hand side dense matrix +inline void DynamicMatrix::subAssign( const DenseMatrix& 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::value && ii < jj ) break; + if( IsUpper::value && ii > jj ) continue; + + for( size_t i=ii; i::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jend ( ( IsLower::value ) + ?( min( ( IsStrictlyLower::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 // Storage order +template< typename MT > // Type of the right-hand side sparse matrix +inline void DynamicMatrix::subAssign( const SparseMatrix& 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 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::subAssign( const SparseMatrix& 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 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 : public DenseMatrix< DynamicMatrix, true > +{ + public: + //**Type definitions**************************************************************************** + typedef DynamicMatrix This; //!< Type of this DynamicMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this DynamicMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef DynamicMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef DynamicMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef Type ElementType; //!< Type of the matrix elements. + typedef SIMDTrait_ 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 Iterator; //!< Iterator over non-constant elements. + typedef DenseIterator 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 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::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::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 > 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& 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 > 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& rhs ); + template< typename MT, bool SO > inline DynamicMatrix& operator+=( const Matrix& rhs ); + template< typename MT, bool SO > inline DynamicMatrix& operator-=( const Matrix& rhs ); + template< typename MT, bool SO > inline DynamicMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_, DynamicMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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_ >::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_ >::value && + HasSIMDAdd< Type, ElementType_ >::value && + !IsDiagonal::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_ >::value && + HasSIMDSub< Type, ElementType_ >::value && + !IsDiagonal::value }; + }; + //********************************************************************************************** + + //********************************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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_ > assign( const DenseMatrix& rhs ); + + template< typename MT > + inline EnableIf_ > assign( const DenseMatrix& rhs ); + + template< typename MT > inline void assign( const DenseMatrix& rhs ); + template< typename MT > inline void assign( const SparseMatrix& rhs ); + template< typename MT > inline void assign( const SparseMatrix& rhs ); + + template< typename MT > + inline DisableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT > + inline EnableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT > inline void addAssign( const DenseMatrix& rhs ); + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + + template< typename MT > + inline DisableIf_ > subAssign ( const DenseMatrix& rhs ); + + template< typename MT > + inline EnableIf_ > subAssign ( const DenseMatrix& rhs ); + + template< typename MT > inline void subAssign( const DenseMatrix& rhs ); + template< typename MT > inline void subAssign( const SparseMatrix& rhs ); + template< typename MT > inline void subAssign( const SparseMatrix& 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::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::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( capacity_ ) ) // The matrix elements +{ + if( IsVectorizable::value ) { + for( size_t j=0UL; j // Data type of the matrix +inline DynamicMatrix::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( capacity_ ) ) // The matrix elements +{ + for( size_t j=0UL; j::value ) { + for( size_t i=m_; i 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::DynamicMatrix( initializer_list< initializer_list > 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( 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::value ) { + for( ; i 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::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( capacity_ ) ) // The matrix elements +{ + for( size_t j=0UL; j::value ) { + for( size_t i=m; i 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::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( capacity_ ) ) // The matrix elements +{ + for( size_t j=0UL; j::value ) { + for( size_t i=M; i // Data type of the matrix +inline DynamicMatrix::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( capacity_ ) ) // The matrix elements +{ + BLAZE_INTERNAL_ASSERT( capacity_ <= m.capacity_, "Invalid capacity estimation" ); + + for( size_t i=0UL; i // Data type of the matrix +inline DynamicMatrix::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::DynamicMatrix( const Matrix& 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( capacity_ ) ) // The matrix elements +{ + for( size_t j=0UL; j::value ? 0UL : m_ ); + i<( IsVectorizable::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::~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::Reference + DynamicMatrix::operator()( size_t i, size_t j ) noexcept +{ + BLAZE_USER_ASSERT( i // Data type of the matrix +inline typename DynamicMatrix::ConstReference + DynamicMatrix::operator()( size_t i, size_t j ) const noexcept +{ + BLAZE_USER_ASSERT( i // Data type of the matrix +inline typename DynamicMatrix::Reference + DynamicMatrix::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::ConstReference + DynamicMatrix::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::Pointer + DynamicMatrix::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::ConstPointer + DynamicMatrix::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::Pointer + DynamicMatrix::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::ConstPointer + DynamicMatrix::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::Iterator + DynamicMatrix::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::ConstIterator + DynamicMatrix::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::ConstIterator + DynamicMatrix::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::Iterator + DynamicMatrix::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::ConstIterator + DynamicMatrix::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::ConstIterator + DynamicMatrix::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& DynamicMatrix::operator=( const Type& rhs ) +{ + for( size_t j=0UL; j 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& + DynamicMatrix::operator=( initializer_list< initializer_list > 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 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& DynamicMatrix::operator=( const Other (&array)[M][N] ) +{ + resize( M, N, false ); + + for( size_t j=0UL; j // Data type of the matrix +inline DynamicMatrix& DynamicMatrix::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& DynamicMatrix::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& DynamicMatrix::operator=( const Matrix& rhs ) +{ + typedef TransExprTrait_ TT; + typedef CTransExprTrait_ CT; + typedef InvExprTrait_ IT; + + if( IsSame::value && (~rhs).isAliased( this ) ) { + transpose(); + } + else if( IsSame::value && (~rhs).isAliased( this ) ) { + ctranspose(); + } + else if( !IsSame::value && (~rhs).canAlias( this ) ) { + DynamicMatrix tmp( ~rhs ); + swap( tmp ); + } + else { + resize( (~rhs).rows(), (~rhs).columns(), false ); + if( IsSparseMatrix::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& DynamicMatrix::operator+=( const Matrix& rhs ) +{ + if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& DynamicMatrix::operator-=( const Matrix& rhs ) +{ + if( (~rhs).rows() != m_ || (~rhs).columns() != n_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& DynamicMatrix::operator*=( const Matrix& 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_, DynamicMatrix >& + DynamicMatrix::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_, DynamicMatrix >& + DynamicMatrix::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::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::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::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::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::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::nonZeros() const +{ + size_t nonzeros( 0UL ); + + for( size_t j=0UL; j // Data type of the matrix +inline size_t DynamicMatrix::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 // Data type of the matrix +inline void DynamicMatrix::reset() +{ + using blaze::clear; + + for( size_t j=0UL; j // Data type of the matrix +inline void DynamicMatrix::reset( size_t j ) +{ + using blaze::clear; + + BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" ); + for( size_t i=0UL; i // Data type of the matrix +inline void DynamicMatrix::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::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( mm*n ); + const size_t min_m( min( m, m_ ) ); + const size_t min_n( min( n, n_ ) ); + + for( size_t j=0UL; j capacity_ ) { + Type* BLAZE_RESTRICT v = allocate( mm*n ); + std::swap( v_, v ); + deallocate( v ); + capacity_ = mm*n; + } + + if( IsVectorizable::value ) { + for( size_t j=0UL; j // Data type of the matrix +inline void DynamicMatrix::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::reserve( size_t elements ) +{ + if( elements > capacity_ ) + { + // Allocating a new array + Type* BLAZE_RESTRICT tmp = allocate( elements ); + + // Initializing the new array + transfer( v_, v_+capacity_, tmp ); + + if( IsVectorizable::value ) { + for( size_t i=capacity_; i // Data type of the matrix +inline DynamicMatrix& DynamicMatrix::transpose() +{ + using std::swap; + + const size_t block( BLOCK_SIZE ); + + if( m_ == n_ ) + { + for( size_t jj=0UL; jjswap( 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& DynamicMatrix::ctranspose() +{ + const size_t block( BLOCK_SIZE ); + + if( m_ == n_ ) + { + for( size_t jj=0UL; jjswap( 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& DynamicMatrix::scale( const Other& scalar ) +{ + for( size_t j=0UL; j // Data type of the matrix +inline void DynamicMatrix::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::adjustRows( size_t minRows ) const noexcept +{ + if( usePadding && IsVectorizable::value ) + return nextMultiple( 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::isIntact() const noexcept +{ + if( m_ * n_ > capacity_ ) + return false; + + if( IsVectorizable::value ) { + for( size_t j=0UL; j // Data type of the matrix +template< typename Other > // Data type of the foreign expression +inline bool DynamicMatrix::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::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::SIMDType + DynamicMatrix::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::SIMDType + DynamicMatrix::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::SIMDType + DynamicMatrix::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::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::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::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::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_::BLAZE_TEMPLATE VectorizedAssign > + DynamicMatrix::assign( const DenseMatrix& 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 // Data type of the matrix +template< typename MT > // Type of the right-hand side dense matrix +inline EnableIf_::BLAZE_TEMPLATE VectorizedAssign > + DynamicMatrix::assign( const DenseMatrix& 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::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 right( (~rhs).begin(j) ); + + for( ; i 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 // Data type of the matrix +template< typename MT > // Type of the right-hand side dense matrix +inline void DynamicMatrix::assign( const DenseMatrix& 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 // Data type of the matrix +template< typename MT > // Type of the right-hand side sparse matrix +inline void DynamicMatrix::assign( const SparseMatrix& 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_ 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::assign( const SparseMatrix& 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_ 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_::BLAZE_TEMPLATE VectorizedAddAssign > + DynamicMatrix::addAssign( const DenseMatrix& 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::value ) + { + v_[j+j*mm_] += (~rhs)(j,j); + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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_::BLAZE_TEMPLATE VectorizedAddAssign > + DynamicMatrix::addAssign( const DenseMatrix& 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::value ); + + for( size_t j=0UL; j::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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_ 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 // Data type of the matrix +template< typename MT > // Type of the right-hand side dense matrix +inline void DynamicMatrix::addAssign( const DenseMatrix& 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::value && ii < jj ) continue; + if( IsUpper::value && ii > jj ) break; + + for( size_t j=jj; j::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t iend ( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::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 // Data type of the matrix +template< typename MT > // Type of the right-hand side sparse matrix +inline void DynamicMatrix::addAssign( const SparseMatrix& 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_ 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::addAssign( const SparseMatrix& 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_ 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_::BLAZE_TEMPLATE VectorizedSubAssign > + DynamicMatrix::subAssign( const DenseMatrix& 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::value ) + { + v_[j+j*mm_] -= (~rhs)(j,j); + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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_::BLAZE_TEMPLATE VectorizedSubAssign > + DynamicMatrix::subAssign( const DenseMatrix& 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::value ); + + for( size_t j=0UL; j::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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_ 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 // Data type of the matrix +template< typename MT > // Type of the right-hand side dense matrix +inline void DynamicMatrix::subAssign( const DenseMatrix& 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::value && ii < jj ) continue; + if( IsUpper::value && ii > jj ) break; + + for( size_t j=jj; j::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t iend ( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::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 // Data type of the matrix +template< typename MT > // Type of the right-hand side sparse matrix +inline void DynamicMatrix::subAssign( const SparseMatrix& 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_ 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::subAssign( const SparseMatrix& 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_ 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& m ); + +template< typename Type, bool SO > +inline void reset( DynamicMatrix& m, size_t i ); + +template< typename Type, bool SO > +inline void clear( DynamicMatrix& m ); + +template< typename Type, bool SO > +inline bool isDefault( const DynamicMatrix& m ); + +template< typename Type, bool SO > +inline bool isIntact( const DynamicMatrix& m ) noexcept; + +template< typename Type, bool SO > +inline void swap( DynamicMatrix& a, DynamicMatrix& 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& 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& 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& 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 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& 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 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& 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& a, DynamicMatrix& b ) noexcept +{ + a.swap( b ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool SO > +struct HasConstDataAccess< DynamicMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool SO > +struct HasMutableDataAccess< DynamicMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool SO > +struct IsAligned< DynamicMatrix > : public BoolConstant +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool SO > +struct IsPadded< DynamicMatrix > : public BoolConstant +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool SO > +struct IsResizable< DynamicMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ADDTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO, typename T2, size_t M, size_t N > +struct AddTrait< DynamicMatrix, StaticMatrix > +{ + using Type = StaticMatrix< AddTrait_, M, N, SO >; +}; + +template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 > +struct AddTrait< DynamicMatrix, StaticMatrix > +{ + using Type = StaticMatrix< AddTrait_, M, N, false >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2 > +struct AddTrait< StaticMatrix, DynamicMatrix > +{ + using Type = StaticMatrix< AddTrait_, M, N, SO >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 > +struct AddTrait< StaticMatrix, DynamicMatrix > +{ + using Type = StaticMatrix< AddTrait_, M, N, false >; +}; + +template< typename T1, bool SO, typename T2, size_t M, size_t N > +struct AddTrait< DynamicMatrix, HybridMatrix > +{ + using Type = HybridMatrix< AddTrait_, M, N, SO >; +}; + +template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 > +struct AddTrait< DynamicMatrix, HybridMatrix > +{ + using Type = HybridMatrix< AddTrait_, M, N, false >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2 > +struct AddTrait< HybridMatrix, DynamicMatrix > +{ + using Type = HybridMatrix< AddTrait_, M, N, SO >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 > +struct AddTrait< HybridMatrix, DynamicMatrix > +{ + using Type = HybridMatrix< AddTrait_, M, N, false >; +}; + +template< typename T1, bool SO, typename T2 > +struct AddTrait< DynamicMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< AddTrait_, SO >; +}; + +template< typename T1, bool SO1, typename T2, bool SO2 > +struct AddTrait< DynamicMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< AddTrait_, false >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO, typename T2, size_t M, size_t N > +struct SubTrait< DynamicMatrix, StaticMatrix > +{ + using Type = StaticMatrix< SubTrait_, M, N, SO >; +}; + +template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 > +struct SubTrait< DynamicMatrix, StaticMatrix > +{ + using Type = StaticMatrix< SubTrait_, M, N, false >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2 > +struct SubTrait< StaticMatrix, DynamicMatrix > +{ + using Type = StaticMatrix< SubTrait_, M, N, SO >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 > +struct SubTrait< StaticMatrix, DynamicMatrix > +{ + using Type = StaticMatrix< SubTrait_, M, N, false >; +}; + +template< typename T1, bool SO, typename T2, size_t M, size_t N > +struct SubTrait< DynamicMatrix, HybridMatrix > +{ + using Type = HybridMatrix< SubTrait_, M, N, SO >; +}; + +template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 > +struct SubTrait< DynamicMatrix, HybridMatrix > +{ + using Type = HybridMatrix< SubTrait_, M, N, false >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2 > +struct SubTrait< HybridMatrix, DynamicMatrix > +{ + using Type = HybridMatrix< SubTrait_, M, N, SO >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 > +struct SubTrait< HybridMatrix, DynamicMatrix > +{ + using Type = HybridMatrix< SubTrait_, M, N, false >; +}; + +template< typename T1, bool SO, typename T2 > +struct SubTrait< DynamicMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< SubTrait_, SO >; +}; + +template< typename T1, bool SO1, typename T2, bool SO2 > +struct SubTrait< DynamicMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< SubTrait_, false >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO, typename T2 > +struct MultTrait< DynamicMatrix, T2, EnableIf_ > > +{ + using Type = DynamicMatrix< MultTrait_, SO >; +}; + +template< typename T1, typename T2, bool SO > +struct MultTrait< T1, DynamicMatrix, EnableIf_ > > +{ + using Type = DynamicMatrix< MultTrait_, SO >; +}; + +template< typename T1, bool SO, typename T2, size_t N > +struct MultTrait< DynamicMatrix, StaticVector > +{ + using Type = DynamicVector< MultTrait_, false >; +}; + +template< typename T1, size_t N, typename T2, bool SO > +struct MultTrait< StaticVector, DynamicMatrix > +{ + using Type = DynamicVector< MultTrait_, true >; +}; + +template< typename T1, bool SO, typename T2, size_t N > +struct MultTrait< DynamicMatrix, HybridVector > +{ + using Type = DynamicVector< MultTrait_, false >; +}; + +template< typename T1, size_t N, typename T2, bool SO > +struct MultTrait< HybridVector, DynamicMatrix > +{ + using Type = DynamicVector< MultTrait_, true >; +}; + +template< typename T1, bool SO, typename T2 > +struct MultTrait< DynamicMatrix, DynamicVector > +{ + using Type = DynamicVector< MultTrait_, false >; +}; + +template< typename T1, typename T2, bool SO > +struct MultTrait< DynamicVector, DynamicMatrix > +{ + using Type = DynamicVector< MultTrait_, true >; +}; + +template< typename T1, bool SO, typename T2, bool AF, bool PF > +struct MultTrait< DynamicMatrix, CustomVector > +{ + using Type = DynamicVector< MultTrait_, false >; +}; + +template< typename T1, bool AF, bool PF, typename T2, bool SO > +struct MultTrait< CustomVector, DynamicMatrix > +{ + using Type = DynamicVector< MultTrait_, true >; +}; + +template< typename T1, bool SO, typename T2 > +struct MultTrait< DynamicMatrix, CompressedVector > +{ + using Type = DynamicVector< MultTrait_, false >; +}; + +template< typename T1, typename T2, bool SO > +struct MultTrait< CompressedVector, DynamicMatrix > +{ + using Type = DynamicVector< MultTrait_, true >; +}; + +template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 > +struct MultTrait< DynamicMatrix, StaticMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 > +struct MultTrait< StaticMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 > +struct MultTrait< DynamicMatrix, HybridMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 > +struct MultTrait< HybridMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, bool SO1, typename T2, bool SO2 > +struct MultTrait< DynamicMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO, typename T2 > +struct DivTrait< DynamicMatrix, T2, EnableIf_ > > +{ + using Type = DynamicMatrix< DivTrait_, SO >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MATHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO, typename T2 > +struct MathTrait< DynamicMatrix, DynamicMatrix > +{ + using HighType = DynamicMatrix< typename MathTrait::HighType, SO >; + using LowType = DynamicMatrix< typename MathTrait::LowType , SO >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO > +struct SubmatrixTrait< DynamicMatrix > +{ + using Type = DynamicMatrix; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO > +struct RowTrait< DynamicMatrix > +{ + using Type = DynamicVector; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO > +struct ColumnTrait< DynamicMatrix > +{ + using Type = DynamicVector; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 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 b( 2, 2.0 ); // Directly, homogeneously initialized 2D vector + CompressedVector c( 2 ); // Empty sparse single precision vector + DynamicVector d; // Default constructed dynamic vector + DynamicMatrix 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, TF > +{ + public: + //**Type definitions**************************************************************************** + typedef DynamicVector This; //!< Type of this DynamicVector instance. + typedef DenseVector BaseType; //!< Base type of this DynamicVector instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef DynamicVector TransposeType; //!< Transpose type for expression template evaluations. + typedef Type ElementType; //!< Type of the vector elements. + typedef SIMDTrait_ 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 Iterator; //!< Iterator over non-constant elements. + typedef DenseIterator 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 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::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::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 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& 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 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& rhs ); + template< typename VT > inline DynamicVector& operator+=( const Vector& rhs ); + template< typename VT > inline DynamicVector& operator-=( const Vector& rhs ); + template< typename VT > inline DynamicVector& operator*=( const Vector& rhs ); + template< typename VT > inline DynamicVector& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_, DynamicVector >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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_ >::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_ >::value && + HasSIMDAdd< Type, ElementType_ >::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_ >::value && + HasSIMDSub< Type, ElementType_ >::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_ >::value && + HasSIMDMult< Type, ElementType_ >::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_ >::value && + HasSIMDDiv< Type, ElementType_ >::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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_ > assign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > assign( const DenseVector& rhs ); + + template< typename VT > inline void assign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > addAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > addAssign( const DenseVector& rhs ); + + template< typename VT > inline void addAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > subAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > subAssign( const DenseVector& rhs ); + + template< typename VT > inline void subAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > multAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > multAssign( const DenseVector& rhs ); + + template< typename VT > inline void multAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > divAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > divAssign( const DenseVector& 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::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::DynamicVector( size_t n ) + : size_ ( n ) // The current size/dimension of the vector + , capacity_( adjustCapacity( n ) ) // The maximum capacity of the vector + , v_ ( allocate( capacity_ ) ) // The vector elements +{ + if( IsVectorizable::value ) { + for( size_t i=size_; i // Transpose flag +inline DynamicVector::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( capacity_ ) ) // The vector elements +{ + for( size_t i=0UL; i::value ) { + for( size_t i=size_; i 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::DynamicVector( initializer_list list ) + : size_ ( list.size() ) // The current size/dimension of the vector + , capacity_( adjustCapacity( size_ ) ) // The maximum capacity of the vector + , v_ ( allocate( 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 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::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( capacity_ ) ) // The vector elements +{ + for( size_t i=0UL; i::value ) { + for( size_t i=n; i 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::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( capacity_ ) ) // The vector elements +{ + for( size_t i=0UL; i::value ) { + for( size_t i=N; i // Transpose flag +inline DynamicVector::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( capacity_ ) ) // The vector elements +{ + BLAZE_INTERNAL_ASSERT( capacity_ <= v.capacity_, "Invalid capacity estimation" ); + + for( size_t i=0UL; i // Transpose flag +inline DynamicVector::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::DynamicVector( const Vector& v ) + : size_ ( (~v).size() ) // The current size/dimension of the vector + , capacity_( adjustCapacity( size_ ) ) // The maximum capacity of the vector + , v_ ( allocate( capacity_ ) ) // The vector elements +{ + for( size_t i=( IsSparseVector::value ? 0UL : size_ ); + i<( IsVectorizable::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::~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::Reference + DynamicVector::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::ConstReference + DynamicVector::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::Reference + DynamicVector::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::ConstReference + DynamicVector::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::Pointer DynamicVector::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::ConstPointer DynamicVector::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::Iterator DynamicVector::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::ConstIterator DynamicVector::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::ConstIterator DynamicVector::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::Iterator DynamicVector::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::ConstIterator DynamicVector::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::ConstIterator DynamicVector::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& DynamicVector::operator=( const Type& rhs ) +{ + for( size_t i=0UL; i 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& DynamicVector::operator=( initializer_list 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 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& DynamicVector::operator=( const Other (&array)[N] ) +{ + resize( N, false ); + + for( size_t i=0UL; i // Transpose flag +inline DynamicVector& DynamicVector::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& DynamicVector::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& DynamicVector::operator=( const Vector& rhs ) +{ + if( (~rhs).canAlias( this ) ) { + DynamicVector tmp( ~rhs ); + swap( tmp ); + } + else { + resize( (~rhs).size(), false ); + if( IsSparseVector::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& DynamicVector::operator+=( const Vector& rhs ) +{ + if( (~rhs).size() != size_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& DynamicVector::operator-=( const Vector& rhs ) +{ + if( (~rhs).size() != size_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& DynamicVector::operator*=( const Vector& rhs ) +{ + if( (~rhs).size() != size_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + if( IsSparseVector::value || (~rhs).canAlias( this ) ) { + DynamicVector 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& DynamicVector::operator/=( const DenseVector& rhs ) +{ + if( (~rhs).size() != size_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + DynamicVector 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_, DynamicVector >& + DynamicVector::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_, DynamicVector >& + DynamicVector::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::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::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::nonZeros() const +{ + size_t nonzeros( 0 ); + + for( size_t i=0UL; i // Transpose flag +inline void DynamicVector::reset() +{ + using blaze::clear; + for( size_t i=0UL; i // Transpose flag +inline void DynamicVector::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::resize( size_t n, bool preserve ) +{ + if( n > capacity_ ) + { + // Allocating a new array + const size_t newCapacity( adjustCapacity( n ) ); + Type* BLAZE_RESTRICT tmp = allocate( newCapacity ); + + // Initializing the new array + if( preserve ) { + transfer( v_, v_+size_, tmp ); + } + + if( IsVectorizable::value ) { + for( size_t i=size_; i::value && n < size_ ) + { + for( size_t i=n; i // Transpose flag +inline void DynamicVector::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::reserve( size_t n ) +{ + if( n > capacity_ ) + { + // Allocating a new array + const size_t newCapacity( adjustCapacity( n ) ); + Type* BLAZE_RESTRICT tmp = allocate( newCapacity ); + + // Initializing the new array + transfer( v_, v_+size_, tmp ); + + if( IsVectorizable::value ) { + for( size_t i=size_; i // Transpose flag +template< typename Other > // Data type of the scalar value +inline DynamicVector& DynamicVector::scale( const Other& scalar ) +{ + for( size_t i=0UL; i // Transpose flag +inline void DynamicVector::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::adjustCapacity( size_t minCapacity ) const noexcept +{ + if( usePadding && IsVectorizable::value ) + return nextMultiple( 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::isIntact() const noexcept +{ + if( size_ > capacity_ ) + return false; + + if( IsNumeric::value ) { + for( size_t i=size_; i // Transpose flag +template< typename Other > // Data type of the foreign expression +inline bool DynamicVector::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::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::SIMDType + DynamicVector::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::SIMDType + DynamicVector::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::SIMDType + DynamicVector::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::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::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::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::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_::BLAZE_TEMPLATE VectorizedAssign > + DynamicVector::assign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedAssign > + DynamicVector::assign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !usePadding || !IsPadded::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_ right( (~rhs).begin() ); + + if( useStreaming && size_ > ( cacheSize/( sizeof(Type) * 3UL ) ) && !(~rhs).isAliased( this ) ) + { + for( ; i // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void DynamicVector::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedAddAssign > + DynamicVector::addAssign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedAddAssign > + DynamicVector::addAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !usePadding || !IsPadded::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_ 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 // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void DynamicVector::addAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedSubAssign > + DynamicVector::subAssign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedSubAssign > + DynamicVector::subAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !usePadding || !IsPadded::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_ 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 // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void DynamicVector::subAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedMultAssign > + DynamicVector::multAssign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedMultAssign > + DynamicVector::multAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !usePadding || !IsPadded::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_ 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 // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void DynamicVector::multAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size_ == (~rhs).size(), "Invalid vector sizes" ); + + const DynamicVector tmp( serial( *this ) ); + + reset(); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedDivAssign > + DynamicVector::divAssign( const DenseVector& 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 // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedDivAssign > + DynamicVector::divAssign( const DenseVector& 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_ 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 +inline void reset( DynamicVector& v ); + +template< typename Type, bool TF > +inline void clear( DynamicVector& v ); + +template< typename Type, bool TF > +inline bool isDefault( const DynamicVector& v ); + +template< typename Type, bool TF > +inline bool isIntact( const DynamicVector& v ) noexcept; + +template< typename Type, bool TF > +inline void swap( DynamicVector& a, DynamicVector& 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& 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& 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 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& 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 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& 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& a, DynamicVector& b ) noexcept +{ + a.swap( b ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool TF > +struct HasConstDataAccess< DynamicVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool TF > +struct HasMutableDataAccess< DynamicVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool TF > +struct IsAligned< DynamicVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool TF > +struct IsPadded< DynamicVector > : public BoolConstant +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool TF > +struct IsResizable< DynamicVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ADDTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool TF, typename T2, size_t N > +struct AddTrait< DynamicVector, StaticVector > +{ + using Type = StaticVector< AddTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct AddTrait< StaticVector, DynamicVector > +{ + using Type = StaticVector< AddTrait_, N, TF >; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct AddTrait< DynamicVector, HybridVector > +{ + using Type = HybridVector< AddTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct AddTrait< HybridVector, DynamicVector > +{ + using Type = HybridVector< AddTrait_, N, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct AddTrait< DynamicVector, DynamicVector > +{ + using Type = DynamicVector< AddTrait_, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool TF, typename T2, size_t N > +struct SubTrait< DynamicVector, StaticVector > +{ + using Type = StaticVector< SubTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct SubTrait< StaticVector, DynamicVector > +{ + using Type = StaticVector< SubTrait_, N, TF >; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct SubTrait< DynamicVector, HybridVector > +{ + using Type = HybridVector< SubTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct SubTrait< HybridVector, DynamicVector > +{ + using Type = HybridVector< SubTrait_, N, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct SubTrait< DynamicVector, DynamicVector > +{ + using Type = DynamicVector< SubTrait_, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool TF, typename T2 > +struct MultTrait< DynamicVector, T2, EnableIf_ > > +{ + using Type = DynamicVector< MultTrait_, TF >; +}; + +template< typename T1, typename T2, bool TF > +struct MultTrait< T1, DynamicVector, EnableIf_ > > +{ + using Type = DynamicVector< MultTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct MultTrait< DynamicVector, StaticVector > +{ + using Type = StaticVector< MultTrait_, N, TF >; +}; + +template< typename T1, typename T2, size_t N > +struct MultTrait< DynamicVector, StaticVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, typename T2, size_t N > +struct MultTrait< DynamicVector, StaticVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct MultTrait< StaticVector, DynamicVector > +{ + using Type = StaticVector< MultTrait_, N, TF >; +}; + +template< typename T1, size_t N, typename T2 > +struct MultTrait< StaticVector, DynamicVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, size_t N, typename T2 > +struct MultTrait< StaticVector, DynamicVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct MultTrait< DynamicVector, HybridVector > +{ + using Type = HybridVector< MultTrait_, N, TF >; +}; + +template< typename T1, typename T2, size_t N > +struct MultTrait< DynamicVector, HybridVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, typename T2, size_t N > +struct MultTrait< DynamicVector, HybridVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct MultTrait< HybridVector, DynamicVector > +{ + using Type = HybridVector< MultTrait_, N, TF >; +}; + +template< typename T1, size_t N, typename T2 > +struct MultTrait< HybridVector, DynamicVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, size_t N, typename T2 > +struct MultTrait< HybridVector, DynamicVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, bool TF, typename T2 > +struct MultTrait< DynamicVector, DynamicVector > +{ + using Type = DynamicVector< MultTrait_, TF >; +}; + +template< typename T1, typename T2 > +struct MultTrait< DynamicVector, DynamicVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, typename T2 > +struct MultTrait< DynamicVector, DynamicVector > +{ + using Type = MultTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// CROSSTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool TF, typename T2 > +struct CrossTrait< DynamicVector, StaticVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct CrossTrait< StaticVector, DynamicVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct CrossTrait< DynamicVector, HybridVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct CrossTrait< HybridVector, DynamicVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct CrossTrait< DynamicVector, DynamicVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool TF, typename T2 > +struct DivTrait< DynamicVector, T2, EnableIf_ > > +{ + using Type = DynamicVector< DivTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct DivTrait< DynamicVector, StaticVector > +{ + using Type = StaticVector< DivTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct DivTrait< StaticVector, DynamicVector > +{ + using Type = StaticVector< DivTrait_, N, TF >; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct DivTrait< DynamicVector, HybridVector > +{ + using Type = HybridVector< DivTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct DivTrait< HybridVector, DynamicVector > +{ + using Type = HybridVector< DivTrait_, N, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct DivTrait< DynamicVector, DynamicVector > +{ + using Type = DynamicVector< DivTrait_, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MATHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool TF, typename T2 > +struct MathTrait< DynamicVector, DynamicVector > +{ + using HighType = DynamicVector< typename MathTrait::HighType, TF >; + using LowType = DynamicVector< typename MathTrait::LowType , TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTORTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool TF > +struct SubvectorTrait< DynamicVector > +{ + using Type = DynamicVector; +}; +/*! \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 + + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 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 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 C( 2, 3 ); // Empty row-major sparse single precision matrix + HybridMatrix D( 3, 2, 4.0F ); // Directly, homogeneously initialized single precision 3x2 matrix + + HybridMatrix E( A ); // Creation of a new row-major matrix as a copy of A + HybridMatrix 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, SO > +{ + public: + //**Type definitions**************************************************************************** + typedef HybridMatrix This; //!< Type of this HybridMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this HybridMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef HybridMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef HybridMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef Type ElementType; //!< Type of the matrix elements. + typedef SIMDTrait_ 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 Iterator; //!< Iterator over non-constant elements. + typedef DenseIterator 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 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::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 > 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& 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 > 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& rhs ); + template< typename MT, bool SO2 > inline HybridMatrix& operator+=( const Matrix& rhs ); + template< typename MT, bool SO2 > inline HybridMatrix& operator-=( const Matrix& rhs ); + template< typename MT, bool SO2 > inline HybridMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_, HybridMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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_ >::value && + IsRowMajorMatrix::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_ >::value && + HasSIMDAdd< Type, ElementType_ >::value && + IsRowMajorMatrix::value && + !IsDiagonal::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_ >::value && + HasSIMDSub< Type, ElementType_ >::value && + IsRowMajorMatrix::value && + !IsDiagonal::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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_ > assign( const DenseMatrix& rhs ); + + template< typename MT, bool SO2 > + inline EnableIf_ > assign( const DenseMatrix& rhs ); + + template< typename MT > inline void assign( const SparseMatrix& rhs ); + template< typename MT > inline void assign( const SparseMatrix& rhs ); + + template< typename MT, bool SO2 > + inline DisableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT, bool SO2 > + inline EnableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + + template< typename MT, bool SO2 > + inline DisableIf_ > subAssign( const DenseMatrix& rhs ); + + template< typename MT, bool SO2 > + inline EnableIf_ > subAssign( const DenseMatrix& rhs ); + + template< typename MT > inline void subAssign( const SparseMatrix& rhs ); + template< typename MT > inline void subAssign( const SparseMatrix& rhs ); + //@} + //********************************************************************************************** + + private: + //********************************************************************************************** + //! Alignment adjustment. + enum : size_t { NN = ( usePadding )?( NextMultiple< SizeT, SizeT >::value ):( N ) }; + //********************************************************************************************** + + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + AlignedArray 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::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::value || NN == N ); + + if( IsNumeric::value ) { + for( size_t i=0UL; i 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::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::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::value ) { + for( size_t i=0UL; i 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::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::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::value ) { + for( size_t j=n; j::value ) { + for( size_t i=m; i 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::HybridMatrix( initializer_list< initializer_list > 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::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::value ) { + for( ; i 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::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::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::value ) { + for( size_t j=n; j::value ) { + for( size_t i=m; i 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::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::value || NN == N ); + + for( size_t i=0UL; i::value ) { + for( size_t j=N2; j::value ) { + for( size_t i=M2; i // Storage order +inline HybridMatrix::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::value || NN == N ); + + for( size_t i=0UL; i::value ) { + for( size_t j=n_; j::value ) { + for( size_t i=m_; i // Storage order +template< typename MT // Type of the foreign matrix + , bool SO2 > // Storage order of the foreign matrix +inline HybridMatrix::HybridMatrix( const Matrix& 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::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::value ? 0UL : n_ ); + j<( IsNumeric::value ? NN : n_ ); + ++j ) { + v_[i*NN+j] = Type(); + } + } + + if( IsNumeric::value ) { + for( size_t i=m_; i // Storage order +inline typename HybridMatrix::Reference + HybridMatrix::operator()( size_t i, size_t j ) noexcept +{ + BLAZE_USER_ASSERT( i // Storage order +inline typename HybridMatrix::ConstReference + HybridMatrix::operator()( size_t i, size_t j ) const noexcept +{ + BLAZE_USER_ASSERT( i // Storage order +inline typename HybridMatrix::Reference + HybridMatrix::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::ConstReference + HybridMatrix::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::Pointer + HybridMatrix::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::ConstPointer + HybridMatrix::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::Pointer + HybridMatrix::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::ConstPointer + HybridMatrix::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::Iterator + HybridMatrix::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::ConstIterator + HybridMatrix::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::ConstIterator + HybridMatrix::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::Iterator + HybridMatrix::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::ConstIterator + HybridMatrix::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::ConstIterator + HybridMatrix::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& HybridMatrix::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 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& + HybridMatrix::operator=( initializer_list< initializer_list > 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 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& HybridMatrix::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 // Storage order +inline HybridMatrix& HybridMatrix::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& HybridMatrix::operator=( const Matrix& rhs ) +{ + using blaze::assign; + + typedef TransExprTrait_ TT; + typedef CTransExprTrait_ CT; + typedef InvExprTrait_ IT; + + if( (~rhs).rows() > M || (~rhs).columns() > N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to hybrid matrix" ); + } + + if( IsSame::value && (~rhs).isAliased( this ) ) { + transpose(); + } + else if( IsSame::value && (~rhs).isAliased( this ) ) { + ctranspose(); + } + else if( !IsSame::value && (~rhs).canAlias( this ) ) { + HybridMatrix tmp( ~rhs ); + resize( tmp.rows(), tmp.columns() ); + assign( *this, tmp ); + } + else { + resize( (~rhs).rows(), (~rhs).columns() ); + if( IsSparseMatrix::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& HybridMatrix::operator+=( const Matrix& 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_ 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& HybridMatrix::operator-=( const Matrix& 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_ 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& HybridMatrix::operator*=( const Matrix& 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_, HybridMatrix >& + HybridMatrix::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_, HybridMatrix >& + HybridMatrix::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::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::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::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::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::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::nonZeros() const +{ + size_t nonzeros( 0UL ); + + for( size_t i=0UL; i // Storage order +inline size_t HybridMatrix::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 // Storage order +inline void HybridMatrix::reset() +{ + using blaze::clear; + + for( size_t i=0UL; i // Storage order +inline void HybridMatrix::reset( size_t i ) +{ + using blaze::clear; + + BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" ); + for( size_t j=0UL; j // Storage order +inline void HybridMatrix::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::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::value && n < n_ ) { + for( size_t i=0UL; i::value && m < m_ ) { + for( size_t i=m; i 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::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& HybridMatrix::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::value && m_ < n_ ) { + for( size_t i=0UL; i::value && m_ > n_ ) { + for( size_t i=n_; i // Storage order +inline HybridMatrix& HybridMatrix::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::value && m_ < n_ ) { + for( size_t i=0UL; i::value && m_ > n_ ) { + for( size_t i=n_; i // Storage order +template< typename Other > // Data type of the scalar value +inline HybridMatrix& HybridMatrix::scale( const Other& scalar ) +{ + for( size_t i=0UL; i // Storage order +inline void HybridMatrix::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 // Storage order +inline void* HybridMatrix::operator new( std::size_t size ) +{ + UNUSED_PARAMETER( size ); + + BLAZE_INTERNAL_ASSERT( size == sizeof( HybridMatrix ), "Invalid number of bytes detected" ); + + return allocate( 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::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( 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::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( 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::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( 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::operator delete( void* ptr ) +{ + deallocate( static_cast( 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::operator delete[]( void* ptr ) +{ + deallocate( static_cast( 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::operator delete( void* ptr, const std::nothrow_t& ) +{ + deallocate( static_cast( 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::operator delete[]( void* ptr, const std::nothrow_t& ) +{ + deallocate( static_cast( 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::isIntact() const noexcept +{ + if( m_ > M || n_ > N ) + return false; + + if( IsNumeric::value ) + { + for( size_t i=0UL; i // Storage order +template< typename Other > // Data type of the foreign expression +inline bool HybridMatrix::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::SIMDType + HybridMatrix::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::SIMDType + HybridMatrix::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::SIMDType + HybridMatrix::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::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::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::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::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_::BLAZE_TEMPLATE VectorizedAssign > + HybridMatrix::assign( const DenseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" ); + + for( size_t i=0UL; i // 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_::BLAZE_TEMPLATE VectorizedAssign > + HybridMatrix::assign( const DenseMatrix& 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::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 // Storage order +template< typename MT > // Type of the right-hand side sparse matrix +inline void HybridMatrix::assign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" ); + + for( size_t i=0UL; i 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::assign( const SparseMatrix& 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 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_::BLAZE_TEMPLATE VectorizedAddAssign > + HybridMatrix::addAssign( const DenseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" ); + + for( size_t i=0UL; i::value ) + { + v_[i*NN+i] += (~rhs)(i,i); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( n_ ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j // 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_::BLAZE_TEMPLATE VectorizedAddAssign > + HybridMatrix::addAssign( const DenseMatrix& 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::value ); + + for( size_t i=0UL; i::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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 // Storage order +template< typename MT > // Type of the right-hand side sparse matrix +inline void HybridMatrix::addAssign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" ); + + for( size_t i=0UL; i 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::addAssign( const SparseMatrix& 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 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_::BLAZE_TEMPLATE VectorizedSubAssign > + HybridMatrix::subAssign( const DenseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" ); + + for( size_t i=0UL; i::value ) + { + v_[i*NN+i] -= (~rhs)(i,i); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( n_ ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j // 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_::BLAZE_TEMPLATE VectorizedSubAssign > + HybridMatrix::subAssign( const DenseMatrix& 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::value ); + + for( size_t i=0UL; i::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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 // Storage order +template< typename MT > // Type of the right-hand side sparse matrix +inline void HybridMatrix::subAssign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" ); + + for( size_t i=0UL; i 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::subAssign( const SparseMatrix& 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 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 : public DenseMatrix< HybridMatrix, true > +{ + public: + //**Type definitions**************************************************************************** + typedef HybridMatrix This; //!< Type of this HybridMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this HybridMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef HybridMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef HybridMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef Type ElementType; //!< Type of the matrix elements. + typedef SIMDTrait_ 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 Iterator; //!< Iterator over non-constant elements. + typedef DenseIterator 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 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::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 > 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& 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 > 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& rhs ); + template< typename MT, bool SO > inline HybridMatrix& operator+=( const Matrix& rhs ); + template< typename MT, bool SO > inline HybridMatrix& operator-=( const Matrix& rhs ); + template< typename MT, bool SO > inline HybridMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_, HybridMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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_ >::value && + IsColumnMajorMatrix::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_ >::value && + HasSIMDAdd< Type, ElementType_ >::value && + IsColumnMajorMatrix::value && + !IsDiagonal::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_ >::value && + HasSIMDSub< Type, ElementType_ >::value && + IsColumnMajorMatrix::value && + !IsDiagonal::value }; + }; + //********************************************************************************************** + + //********************************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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_ > assign( const DenseMatrix& rhs ); + + template< typename MT, bool SO > + inline EnableIf_ > assign( const DenseMatrix& rhs ); + + template< typename MT > inline void assign( const SparseMatrix& rhs ); + template< typename MT > inline void assign( const SparseMatrix& rhs ); + + template< typename MT, bool SO > + inline DisableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT, bool SO > + inline EnableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + + template< typename MT, bool SO > + inline DisableIf_ > subAssign( const DenseMatrix& rhs ); + + template< typename MT, bool SO > + inline EnableIf_ > subAssign( const DenseMatrix& rhs ); + + template< typename MT > inline void subAssign( const SparseMatrix& rhs ); + template< typename MT > inline void subAssign( const SparseMatrix& rhs ); + //@} + //********************************************************************************************** + + private: + //********************************************************************************************** + //! Alignment adjustment. + enum : size_t { MM = ( usePadding )?( NextMultiple< SizeT, SizeT >::value ):( M ) }; + //********************************************************************************************** + + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + AlignedArray 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::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::value || MM == M ); + + if( IsNumeric::value ) { + for( size_t i=0UL; i 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::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::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::value ) { + for( size_t i=0UL; i 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::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::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::value ) { + for( size_t i=m; i::value ) { + for( size_t j=n; j 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::HybridMatrix( initializer_list< initializer_list > 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::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::value ) { + for( ; j::value ) { + for( ; i 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::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::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::value ) { + for( size_t i=m; i::value ) { + for( size_t j=n; j 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::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::value || MM == M ); + + for( size_t j=0UL; j::value ) { + for( size_t i=M2; i::value ) { + for( size_t j=N2; j // Number of columns +inline HybridMatrix::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::value || MM == M ); + + for( size_t j=0UL; j::value ) { + for( size_t i=m_; i::value ) { + for( size_t j=n_; j // Number of columns +template< typename MT // Type of the foreign matrix + , bool SO2 > // Storage order of the foreign matrix +inline HybridMatrix::HybridMatrix( const Matrix& 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::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::value ? 0UL : m_ ); + i<( IsNumeric::value ? MM : m_ ); + ++i ) { + v_[i+j*MM] = Type(); + } + } + + if( IsNumeric::value ) { + for( size_t j=n_; j // Number of columns +inline typename HybridMatrix::Reference + HybridMatrix::operator()( size_t i, size_t j ) noexcept +{ + BLAZE_USER_ASSERT( i // Number of columns +inline typename HybridMatrix::ConstReference + HybridMatrix::operator()( size_t i, size_t j ) const noexcept +{ + BLAZE_USER_ASSERT( i // Number of columns +inline typename HybridMatrix::Reference + HybridMatrix::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::ConstReference + HybridMatrix::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::Pointer + HybridMatrix::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::ConstPointer + HybridMatrix::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::Pointer + HybridMatrix::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::ConstPointer + HybridMatrix::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::Iterator + HybridMatrix::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::ConstIterator + HybridMatrix::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::ConstIterator + HybridMatrix::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::Iterator + HybridMatrix::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::ConstIterator + HybridMatrix::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::ConstIterator + HybridMatrix::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& + HybridMatrix::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 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& + HybridMatrix::operator=( initializer_list< initializer_list > 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 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& + HybridMatrix::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 // Number of columns +inline HybridMatrix& + HybridMatrix::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& HybridMatrix::operator=( const Matrix& rhs ) +{ + using blaze::assign; + + typedef TransExprTrait_ TT; + typedef CTransExprTrait_ CT; + typedef InvExprTrait_ IT; + + if( (~rhs).rows() > M || (~rhs).columns() > N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to hybrid matrix" ); + } + + if( IsSame::value && (~rhs).isAliased( this ) ) { + transpose(); + } + else if( IsSame::value && (~rhs).isAliased( this ) ) { + ctranspose(); + } + else if( !IsSame::value && (~rhs).canAlias( this ) ) { + HybridMatrix tmp( ~rhs ); + resize( tmp.rows(), tmp.columns() ); + assign( *this, tmp ); + } + else { + resize( (~rhs).rows(), (~rhs).columns() ); + if( IsSparseMatrix::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& HybridMatrix::operator+=( const Matrix& 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_ 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& HybridMatrix::operator-=( const Matrix& 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_ 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& HybridMatrix::operator*=( const Matrix& 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_, HybridMatrix >& + HybridMatrix::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_, HybridMatrix >& + HybridMatrix::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::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::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::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::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::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::nonZeros() const +{ + size_t nonzeros( 0UL ); + + for( size_t j=0UL; j // Number of columns +inline size_t HybridMatrix::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 // Number of columns +inline void HybridMatrix::reset() +{ + using blaze::clear; + + for( size_t j=0UL; j // Number of columns +inline void HybridMatrix::reset( size_t j ) +{ + using blaze::clear; + + BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" ); + for( size_t i=0UL; i // Number of columns +inline void HybridMatrix::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::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::value && m < m_ ) { + for( size_t j=0UL; j::value && n < n_ ) { + for( size_t j=n; j 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::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& HybridMatrix::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::value && n_ < m_ ) { + for( size_t j=0UL; j::value && n_ > m_ ) { + for( size_t j=m_; j // Number of columns +inline HybridMatrix& HybridMatrix::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::value && n_ < m_ ) { + for( size_t j=0UL; j::value && n_ > m_ ) { + for( size_t j=m_; j // Number of columns +template< typename Other > // Data type of the scalar value +inline HybridMatrix& + HybridMatrix::scale( const Other& scalar ) +{ + for( size_t j=0UL; j // Number of columns +inline void HybridMatrix::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 // Number of columns +inline void* HybridMatrix::operator new( std::size_t size ) +{ + UNUSED_PARAMETER( size ); + + BLAZE_INTERNAL_ASSERT( size == sizeof( HybridMatrix ), "Invalid number of bytes detected" ); + + return allocate( 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::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( 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::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( 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::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( 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::operator delete( void* ptr ) +{ + deallocate( static_cast( 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::operator delete[]( void* ptr ) +{ + deallocate( static_cast( 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::operator delete( void* ptr, const std::nothrow_t& ) +{ + deallocate( static_cast( 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::operator delete[]( void* ptr, const std::nothrow_t& ) +{ + deallocate( static_cast( 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::isIntact() const noexcept +{ + if( m_ > M || n_ > N ) + return false; + + if( IsNumeric::value ) + { + for( size_t j=0UL; j // Number of columns +template< typename Other > // Data type of the foreign expression +inline bool HybridMatrix::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::SIMDType + HybridMatrix::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::SIMDType + HybridMatrix::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::SIMDType + HybridMatrix::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::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::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::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::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_::BLAZE_TEMPLATE VectorizedAssign > + HybridMatrix::assign( const DenseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" ); + + for( size_t j=0UL; j // 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_::BLAZE_TEMPLATE VectorizedAssign > + HybridMatrix::assign( const DenseMatrix& 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::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 // Number of columns +template< typename MT > // Type of the right-hand side sparse matrix +inline void HybridMatrix::assign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" ); + + for( size_t j=0UL; j 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::assign( const SparseMatrix& 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 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_::BLAZE_TEMPLATE VectorizedAddAssign > + HybridMatrix::addAssign( const DenseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" ); + + for( size_t j=0UL; j::value ) + { + v_[j+j*MM] += (~rhs)(j,j); + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( m_ ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i // 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_::BLAZE_TEMPLATE VectorizedAddAssign > + HybridMatrix::addAssign( const DenseMatrix& 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::value ); + + for( size_t j=0UL; j::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Number of columns +template< typename MT > // Type of the right-hand side sparse matrix +inline void HybridMatrix::addAssign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" ); + + for( size_t j=0UL; j 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::addAssign( const SparseMatrix& 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 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_::BLAZE_TEMPLATE VectorizedSubAssign > + HybridMatrix::subAssign( const DenseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" ); + + for( size_t j=0UL; j::value ) + { + v_[j+j*MM] -= (~rhs)(j,j); + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( m_ ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i // 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_::BLAZE_TEMPLATE VectorizedSubAssign > + HybridMatrix::subAssign( const DenseMatrix& 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::value ); + + for( size_t j=0UL; j::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Number of columns +template< typename MT > // Type of the right-hand side sparse matrix +inline void HybridMatrix::subAssign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" ); + + typedef ConstIterator_ RhsConstIterator; + + for( size_t j=0UL; jindex()+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::subAssign( const SparseMatrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_SYMMETRIC_MATRIX_TYPE( MT ); + + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == m_ && (~rhs).columns() == n_, "Invalid matrix size" ); + + typedef ConstIterator_ RhsConstIterator; + + for( size_t i=0UL; iindex()*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; +/*! \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; +/*! \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; +/*! \endcond */ +//************************************************************************************************* + + + + + + + + +//================================================================================================= +// +// STATICMATRIX OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name HybridMatrix operators */ +//@{ +template< typename Type, size_t M, size_t N, bool SO > +inline void reset( HybridMatrix& m ); + +template< typename Type, size_t M, size_t N, bool SO > +inline void reset( HybridMatrix& m, size_t i ); + +template< typename Type, size_t M, size_t N, bool SO > +inline void clear( HybridMatrix& m ); + +template< typename Type, size_t M, size_t N, bool SO > +inline bool isDefault( const HybridMatrix& m ); + +template< typename Type, size_t M, size_t N, bool SO > +inline bool isIntact( const HybridMatrix& m ) noexcept; + +template< typename Type, size_t M, size_t N, bool SO > +inline void swap( HybridMatrix& a, HybridMatrix& 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& 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& 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& 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 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& 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 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& 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& a, HybridMatrix& b ) noexcept +{ + a.swap( b ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t M, size_t N, bool SO > +struct HasConstDataAccess< HybridMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t M, size_t N, bool SO > +struct HasMutableDataAccess< HybridMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t M, size_t N, bool SO > +struct IsAligned< HybridMatrix > : public BoolConstant +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t M, size_t N, bool SO > +struct IsPadded< HybridMatrix > : public BoolConstant +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t M, size_t N, bool SO > +struct IsResizable< HybridMatrix > : 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, StaticMatrix > +{ + using Type = StaticMatrix< AddTrait_, 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, StaticMatrix > +{ + using Type = StaticMatrix< AddTrait_, 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, HybridMatrix > +{ + using Type = StaticMatrix< AddTrait_, 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, HybridMatrix > +{ + using Type = StaticMatrix< AddTrait_, 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, HybridMatrix > +{ + using Type = HybridMatrix< AddTrait_, ( 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, HybridMatrix > +{ + using Type = HybridMatrix< AddTrait_, ( 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, StaticMatrix > +{ + using Type = StaticMatrix< SubTrait_, 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, StaticMatrix > +{ + using Type = StaticMatrix< SubTrait_, 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, HybridMatrix > +{ + using Type = StaticMatrix< SubTrait_, 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, HybridMatrix > +{ + using Type = StaticMatrix< SubTrait_, 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, HybridMatrix > +{ + using Type = HybridMatrix< SubTrait_, ( 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, HybridMatrix > +{ + using Type = HybridMatrix< SubTrait_, ( 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, T2, EnableIf_ > > +{ + using Type = HybridMatrix< MultTrait_, M, N, SO >; +}; + +template< typename T1, typename T2, size_t M, size_t N, bool SO > +struct MultTrait< T1, HybridMatrix, EnableIf_ > > +{ + using Type = HybridMatrix< MultTrait_, M, N, SO >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2, size_t K > +struct MultTrait< HybridMatrix, StaticVector > +{ + using Type = HybridVector< MultTrait_, M, false >; +}; + +template< typename T1, size_t K, typename T2, size_t M, size_t N, bool SO > +struct MultTrait< StaticVector, HybridMatrix > +{ + using Type = HybridVector< MultTrait_, N, true >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2, size_t K > +struct MultTrait< HybridMatrix, HybridVector > +{ + using Type = HybridVector< MultTrait_, M, false >; +}; + +template< typename T1, size_t K, typename T2, size_t M, size_t N, bool SO > +struct MultTrait< HybridVector, HybridMatrix > +{ + using Type = HybridVector< MultTrait_, N, true >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2 > +struct MultTrait< HybridMatrix, DynamicVector > +{ + using Type = HybridVector< MultTrait_, M, false >; +}; + +template< typename T1, typename T2, size_t M, size_t N, bool SO > +struct MultTrait< DynamicVector, HybridMatrix > +{ + using Type = HybridVector< MultTrait_, N, true >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2, bool AF, bool PF > +struct MultTrait< HybridMatrix, CustomVector > +{ + using Type = HybridVector< MultTrait_, M, false >; +}; + +template< typename T1, bool AF, bool PF, typename T2, size_t M, size_t N, bool SO > +struct MultTrait< CustomVector, HybridMatrix > +{ + using Type = HybridVector< MultTrait_, N, true >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2 > +struct MultTrait< HybridMatrix, CompressedVector > +{ + using Type = HybridVector< MultTrait_, M, false >; +}; + +template< typename T1, typename T2, size_t M, size_t N, bool SO > +struct MultTrait< CompressedVector, HybridMatrix > +{ + using Type = HybridVector< MultTrait_, 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, StaticMatrix > +{ + using Type = HybridMatrix< MultTrait_, 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, HybridMatrix > +{ + using Type = HybridMatrix< MultTrait_, 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, HybridMatrix > +{ + using Type = HybridMatrix< MultTrait_, 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, T2, EnableIf_ > > +{ + using Type = HybridMatrix< DivTrait_, 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, HybridMatrix > +{ + using HighType = HybridMatrix< typename MathTrait::HighType, M, N, SO >; + using LowType = HybridMatrix< typename MathTrait::LowType , M, N, SO >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t M, size_t N, bool SO > +struct SubmatrixTrait< HybridMatrix > +{ + using Type = HybridMatrix; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t M, size_t N, bool SO > +struct RowTrait< HybridMatrix > +{ + using Type = HybridVector; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t M, size_t N, bool SO > +struct ColumnTrait< HybridMatrix > +{ + using Type = HybridVector; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 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 b( 2, 2.0 ); // Directly, homogeneously initialized 2D vector + CompressedVector c( 2 ); // Empty sparse single precision vector + HybridVector d; // Default constructed hybrid vector + StaticMatrix 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, TF > +{ + public: + //**Type definitions**************************************************************************** + typedef HybridVector This; //!< Type of this HybridVector instance. + typedef DenseVector BaseType; //!< Base type of this HybridVector instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef HybridVector TransposeType; //!< Transpose type for expression template evaluations. + typedef Type ElementType; //!< Type of the vector elements. + typedef SIMDTrait_ 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 Iterator; //!< Iterator over non-constant elements. + typedef DenseIterator 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 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::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 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& 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 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& rhs ); + template< typename VT > inline HybridVector& operator+=( const Vector& rhs ); + template< typename VT > inline HybridVector& operator-=( const Vector& rhs ); + template< typename VT > inline HybridVector& operator*=( const Vector& rhs ); + template< typename VT > inline HybridVector& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_, HybridVector >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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_ >::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_ >::value && + HasSIMDAdd< Type, ElementType_ >::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_ >::value && + HasSIMDSub< Type, ElementType_ >::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_ >::value && + HasSIMDMult< Type, ElementType_ >::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_ >::value && + HasSIMDDiv< Type, ElementType_ >::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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_ > assign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > assign( const DenseVector& rhs ); + + template< typename VT > inline void assign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > addAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > addAssign( const DenseVector& rhs ); + + template< typename VT > inline void addAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > subAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > subAssign( const DenseVector& rhs ); + + template< typename VT > inline void subAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > multAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > multAssign( const DenseVector& rhs ); + + template< typename VT > inline void multAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > divAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > divAssign( const DenseVector& rhs ); + //@} + //********************************************************************************************** + + private: + //********************************************************************************************** + //! Alignment adjustment. + enum : size_t { NN = ( usePadding )?( NextMultiple< SizeT, SizeT >::value ):( N ) }; + //********************************************************************************************** + + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + AlignedArray 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::HybridVector() + : v_ () // The statically allocated vector elements + , size_( 0UL ) // The current size/dimension of the vector +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + if( IsNumeric::value ) { + for( size_t i=0UL; i 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::HybridVector( size_t n ) + : v_ () // The statically allocated vector elements + , size_( n ) // The current size/dimension of the vector +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + if( n > N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid size for hybrid vector" ); + } + + if( IsNumeric::value ) { + for( size_t i=0UL; i 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::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::value || NN == N ); + + if( n > N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid size for hybrid vector" ); + } + + for( size_t i=0UL; i::value ) { + for( size_t i=n; i 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::HybridVector( initializer_list list ) + : v_ () // The statically allocated vector elements + , size_( list.size() ) // The current size/dimension of the vector +{ + BLAZE_STATIC_ASSERT( IsVectorizable::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 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::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::value || NN == N ); + + if( n > N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of hybrid vector" ); + } + + for( size_t i=0UL; i::value ) { + for( size_t i=n; i 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::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::value || NN == N ); + + for( size_t i=0UL; i::value ) { + for( size_t i=M; i // Transpose flag +inline HybridVector::HybridVector( const HybridVector& v ) + : v_ () // The statically allocated vector elements + , size_( v.size_ ) // The current size/dimension of the vector +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + for( size_t i=0UL; i::value ) { + for( size_t i=size_; i // Transpose flag +template< typename VT > // Type of the foreign vector +inline HybridVector::HybridVector( const Vector& v ) + : v_ () // The statically allocated vector elements + , size_( (~v).size() ) // The current size/dimension of the vector +{ + using blaze::assign; + + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + if( (~v).size() > N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of hybrid vector" ); + } + + for( size_t i=( IsSparseVector::value ? 0UL : size_ ); + i<( IsNumeric::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::Reference + HybridVector::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::ConstReference + HybridVector::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::Reference + HybridVector::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::ConstReference + HybridVector::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::Pointer HybridVector::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::ConstPointer HybridVector::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::Iterator HybridVector::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::ConstIterator HybridVector::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::ConstIterator HybridVector::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::Iterator HybridVector::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::ConstIterator HybridVector::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::ConstIterator HybridVector::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& HybridVector::operator=( const Type& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size_ <= N, "Invalid size detected" ); + + for( size_t i=0UL; i 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& HybridVector::operator=( initializer_list 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 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& HybridVector::operator=( const Other (&array)[M] ) +{ + BLAZE_STATIC_ASSERT( M <= N ); + + resize( M, false ); + + for( size_t i=0UL; i // Transpose flag +inline HybridVector& HybridVector::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& HybridVector::operator=( const Vector& 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::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& HybridVector::operator+=( const Vector& rhs ) +{ + using blaze::addAssign; + + if( (~rhs).size() != size_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& HybridVector::operator-=( const Vector& rhs ) +{ + using blaze::subAssign; + + if( (~rhs).size() != size_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + if( (~rhs).canAlias( this ) ) { + const ResultType_ 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& HybridVector::operator*=( const Vector& rhs ) +{ + using blaze::multAssign; + + if( (~rhs).size() != size_ ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + if( IsSparseVector::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& HybridVector::operator/=( const DenseVector& 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_, HybridVector >& + HybridVector::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_, HybridVector >& + HybridVector::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::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::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::nonZeros() const +{ + size_t nonzeros( 0 ); + + for( size_t i=0UL; i // Transpose flag +inline void HybridVector::reset() +{ + using blaze::clear; + for( size_t i=0UL; i // Transpose flag +inline void HybridVector::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::resize( size_t n, bool preserve ) +{ + UNUSED_PARAMETER( preserve ); + + if( n > N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid size for hybrid vector" ); + } + + if( IsVectorizable::value && n < size_ ) { + for( size_t i=n; i 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::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& HybridVector::scale( const Other& scalar ) +{ + for( size_t i=0; i // Transpose flag +inline void HybridVector::swap( HybridVector& v ) noexcept +{ + using std::swap; + + const size_t maxsize( max( size_, v.size_ ) ); + for( size_t i=0UL; i // Transpose flag +inline void* HybridVector::operator new( std::size_t size ) +{ + UNUSED_PARAMETER( size ); + + BLAZE_INTERNAL_ASSERT( size == sizeof( HybridVector ), "Invalid number of bytes detected" ); + + return allocate( 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::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( 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::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( 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::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( 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::operator delete( void* ptr ) +{ + deallocate( static_cast( 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::operator delete[]( void* ptr ) +{ + deallocate( static_cast( 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::operator delete( void* ptr, const std::nothrow_t& ) +{ + deallocate( static_cast( 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::operator delete[]( void* ptr, const std::nothrow_t& ) +{ + deallocate( static_cast( 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::isIntact() const noexcept +{ + if( size_ > N ) + return false; + + if( IsNumeric::value ) { + for( size_t i=size_; i // Transpose flag +template< typename Other > // Data type of the foreign expression +inline bool HybridVector::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::SIMDType + HybridVector::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::SIMDType + HybridVector::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::SIMDType + HybridVector::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::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::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::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::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_::BLAZE_TEMPLATE VectorizedAssign > + HybridVector::assign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" ); + + for( size_t i=0UL; i // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedAssign > + HybridVector::assign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" ); + + const bool remainder( !usePadding || !IsPadded::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 // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void HybridVector::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedAddAssign > + HybridVector::addAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" ); + + for( size_t i=0UL; i // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedAddAssign > + HybridVector::addAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" ); + + const bool remainder( !usePadding || !IsPadded::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 // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void HybridVector::addAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedSubAssign > + HybridVector::subAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" ); + + for( size_t i=0UL; i // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedSubAssign > + HybridVector::subAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" ); + + const bool remainder( !usePadding || !IsPadded::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 // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void HybridVector::subAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedMultAssign > + HybridVector::multAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" ); + + for( size_t i=0UL; i // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedMultAssign > + HybridVector::multAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" ); + + const bool remainder( !usePadding || !IsPadded::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 // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void HybridVector::multAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" ); + + const HybridVector tmp( serial( *this ) ); + + reset(); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedDivAssign > + HybridVector::divAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == size_, "Invalid vector sizes" ); + + for( size_t i=0UL; i // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedDivAssign > + HybridVector::divAssign( const DenseVector& 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 // Transpose flag +class HybridVector; +/*! \endcond */ +//************************************************************************************************* + + + + + + + + +//================================================================================================= +// +// HYBRIDVECTOR OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name HybridVector operators */ +//@{ +template< typename Type, size_t N, bool TF > +inline void reset( HybridVector& v ); + +template< typename Type, size_t N, bool TF > +inline void clear( HybridVector& v ); + +template< typename Type, size_t N, bool TF > +inline bool isDefault( const HybridVector& v ); + +template< typename Type, size_t N, bool TF > +inline bool isIntact( const HybridVector& v ); + +template< typename Type, size_t N, bool TF > +inline void swap( HybridVector& a, HybridVector& 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& 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& 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 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& 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 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& 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& a, HybridVector& b ) noexcept +{ + a.swap( b ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t N, bool TF > +struct HasConstDataAccess< HybridVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t N, bool TF > +struct HasMutableDataAccess< HybridVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t N, bool TF > +struct IsAligned< HybridVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t N, bool TF > +struct IsPadded< HybridVector > : public BoolConstant +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t N, bool TF > +struct IsResizable< HybridVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ADDTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t M, bool TF, typename T2, size_t N > +struct AddTrait< HybridVector, StaticVector > +{ + using Type = StaticVector< AddTrait_, N, TF >; +}; + +template< typename T1, size_t M, bool TF, typename T2, size_t N > +struct AddTrait< StaticVector, HybridVector > +{ + using Type = StaticVector< AddTrait_, M, TF >; +}; + +template< typename T1, size_t M, bool TF, typename T2, size_t N > +struct AddTrait< HybridVector, HybridVector > +{ + using Type = HybridVector< AddTrait_, ( 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, StaticVector > +{ + using Type = StaticVector< SubTrait_, N, TF >; +}; + +template< typename T1, size_t M, bool TF, typename T2, size_t N > +struct SubTrait< StaticVector, HybridVector > +{ + using Type = StaticVector< SubTrait_, M, TF >; +}; + +template< typename T1, size_t M, bool TF, typename T2, size_t N > +struct SubTrait< HybridVector, HybridVector > +{ + using Type = HybridVector< SubTrait_, ( M < N )?( M ):( N ), TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t N, bool TF, typename T2 > +struct MultTrait< HybridVector, T2, EnableIf_ > > +{ + using Type = HybridVector< MultTrait_, N, TF >; +}; + +template< typename T1, typename T2, size_t N, bool TF > +struct MultTrait< T1, HybridVector, EnableIf_ > > +{ + using Type = HybridVector< MultTrait_, N, TF >; +}; + +template< typename T1, size_t M, bool TF, typename T2, size_t N > +struct MultTrait< HybridVector, StaticVector > +{ + using Type = StaticVector< MultTrait_, N, TF >; +}; + +template< typename T1, size_t M, typename T2, size_t N > +struct MultTrait< HybridVector, StaticVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, size_t M, typename T2, size_t N > +struct MultTrait< HybridVector, StaticVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, size_t M, bool TF, typename T2, size_t N > +struct MultTrait< StaticVector, HybridVector > +{ + using Type = StaticVector< MultTrait_, M, TF >; +}; + +template< typename T1, size_t M, typename T2, size_t N > +struct MultTrait< StaticVector, HybridVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, size_t M, typename T2, size_t N > +struct MultTrait< StaticVector, HybridVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, size_t M, bool TF, typename T2, size_t N > +struct MultTrait< HybridVector, HybridVector > +{ + using Type = HybridVector< MultTrait_, ( M < N )?( M ):( N ), TF >; +}; + +template< typename T1, size_t M, typename T2, size_t N > +struct MultTrait< HybridVector, HybridVector > +{ + using Type = DynamicMatrix< MultTrait_, false >; +}; + +template< typename T1, size_t M, typename T2, size_t N > +struct MultTrait< HybridVector, HybridVector > +{ + using Type = MultTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// CROSSTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t N, bool TF, typename T2 > +struct CrossTrait< HybridVector, StaticVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct CrossTrait< StaticVector, HybridVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, size_t M, bool TF, typename T2, size_t N > +struct CrossTrait< HybridVector, HybridVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t N, bool TF, typename T2 > +struct DivTrait< HybridVector, T2, EnableIf_ > > +{ + using Type = HybridVector< DivTrait_, N, TF >; +}; + +template< typename T1, size_t M, bool TF, typename T2, size_t N > +struct DivTrait< HybridVector, StaticVector > +{ + using Type = StaticVector< DivTrait_, N, TF >; +}; + +template< typename T1, size_t M, bool TF, typename T2, size_t N > +struct DivTrait< StaticVector, HybridVector > +{ + using Type = StaticVector< DivTrait_, M, TF >; +}; + +template< typename T1, size_t M, bool TF, typename T2, size_t N > +struct DivTrait< HybridVector, HybridVector > +{ + using Type = HybridVector< DivTrait_, ( M < N )?( M ):( N ), TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MATHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t N, bool TF, typename T2 > +struct MathTrait< HybridVector, HybridVector > +{ + using HighType = StaticVector< typename MathTrait::HighType, N, TF >; + using LowType = StaticVector< typename MathTrait::LowType , N, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTORTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t N, bool TF > +struct SubvectorTrait< HybridVector > +{ + using Type = HybridVector; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// INVERSION FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Inversion functions */ +//@{ +template< typename MT, bool SO > +inline void invert( DenseMatrix& dm ); + +template< InversionFlag IF, typename MT, bool SO > +inline void invert( DenseMatrix& 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 or \c complex 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& dm ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( (~dm).rows() == 2UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( (~dm).columns() == 2UL, "Invalid number of columns detected" ); + + typedef ElementType_ 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 or \c complex 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& dm ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( (~dm).rows() == 3UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( (~dm).columns() == 3UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix 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 or \c complex 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& dm ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( (~dm).rows() == 4UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( (~dm).columns() == 4UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix 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 or \c complex 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& dm ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( (~dm).rows() == 5UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( (~dm).columns() == 5UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix 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 or \c complex 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& dm ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_INTERNAL_ASSERT( (~dm).rows() == 6UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( (~dm).columns() == 6UL, "Invalid number of columns detected" ); + + typedef ElementType_ ET; + + const StaticMatrix 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 or \c complex 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& 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 or \c complex 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& dm ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + const size_t n( min( (~dm).rows(), (~dm).columns() ) ); + const std::unique_ptr 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 or \c complex 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& dm ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_USER_ASSERT( isSymmetric( ~dm ), "Invalid non-symmetric matrix detected" ); + + const char uplo( ( SO )?( 'L' ):( 'U' ) ); + const std::unique_ptr 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 or \c complex 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_ > > + invertByLDLH( DenseMatrix& 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 or \c complex 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_ > > + invertByLDLH( DenseMatrix& dm ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_USER_ASSERT( isHermitian( ~dm ), "Invalid non-Hermitian matrix detected" ); + + const char uplo( ( SO )?( 'L' ):( 'U' ) ); + const std::unique_ptr 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 or \c complex 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& dm ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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( A ); // Inversion of a general matrix + invertNxN( A ); // Inversion of a symmetric indefinite matrix + invertNxN( A ); // Inversion of a Hermitian indefinite matrix + invertNxN( 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 or \c complex 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& dm ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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 or \c complex 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& dm ) +{ + invert( ~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( A ); // Inversion of a general matrix + invert( A ); // Inversion of a symmetric indefinite matrix + invert( A ); // Inversion of a Hermitian indefinite matrix + invert( 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 or \c complex 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& dm ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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( ~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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// LLH DECOMPOSITION FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LLH decomposition functions */ +//@{ +template< typename MT1, bool SO1, typename MT2, bool SO2 > +void llh( const DenseMatrix& A, DenseMatrix& 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 A( 32, 32 ); + // ... Initialization of A as positive definite matrix + + blaze::DynamicMatrix 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, or +// \c complex 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& A, DenseMatrix& L ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT1 ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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_ ); + + if( !isSquare( ~A ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" ); + } + + const size_t n( (~A).rows() ); + + if( ( !IsResizable::value && ( (~L).rows() != n || (~L).columns() != n ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Dimensions of fixed size matrix do not match" ); + } + + DerestrictTrait_ l( derestrict( ~L ) ); + + resize( ~L, n, n ); + reset( l ); + + if( IsRowMajorMatrix::value ) { + for( size_t i=0UL; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseMatrix& Q, DenseMatrix& 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_ > > + lq_backend( MT1& A, const ElementType_* 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_ > > + lq_backend( MT1& A, const ElementType_* 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 A( 32, 16 ); + // ... Initialization of A + + blaze::DynamicMatrix L( 32, 16 ); + blaze::DynamicMatrix 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, or +// \c complex 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& A, DenseMatrix& L, DenseMatrix& Q ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT1 ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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_ ); + + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT3 ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + typedef ElementType_ ET1; + + const size_t m( (~A).rows() ); + const size_t n( (~A).columns() ); + const size_t mindim( min( m, n ) ); + + if( ( !IsResizable::value && ( (~L).rows() != m || (~L).columns() != mindim ) ) || + ( !IsResizable::value && ( (~Q).rows() != mindim || (~Q).columns() != n ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Dimensions of fixed size matrix do not match" ); + } + + if( IsSquare::value && m != mindim ) { + BLAZE_THROW_INVALID_ARGUMENT( "Square matrix cannot be resized to m-by-min(m,n)" ); + } + + const std::unique_ptr tau( new ET1[mindim] ); + DerestrictTrait_ l( derestrict( ~L ) ); + + if( m < n ) + { + (~Q) = A; + gelqf( ~Q, tau.get() ); + + resize( ~L, m, m ); + reset( l ); + + for( size_t i=0UL; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseMatrix& L, + DenseMatrix& U, Matrix& 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& A, Matrix& P ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT1 ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 ); + + typedef ElementType_ 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 helper( new int[mindim + size] ); + int* ipiv ( helper.get() ); + int* permut( ipiv + mindim ); + + getrf( ~A, ipiv ); + + for( size_t i=0UL; i \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 A; + // ... Resizing and initialization + + blaze::DynamicMatrix L, U, P; + + lu( A, L, U, P ); // LU decomposition of a row-major matrix + + assert( A == L * U * P ); + \endcode + + \code + blaze::DynamicMatrix A; + // ... Resizing and initialization + + blaze::DynamicMatrix 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, or +// \c complex 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& A, DenseMatrix& L, + DenseMatrix& U, Matrix& P ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT1 ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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_ ET2; + typedef ElementType_ 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::value && ( (~L).rows() != m || (~L).columns() != mindim ) ) || + ( !IsResizable::value && ( (~U).rows() != mindim || (~U).columns() != n ) ) || + ( !IsResizable::value && ( (~P).rows() != size || (~P).columns() != size ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Dimensions of fixed size matrix do not match" ); + } + + if( ( IsSquare::value && n < m ) || ( IsSquare::value && m < n ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Square matrix cannot be resized to m-by-n" ); + } + + DerestrictTrait_ l( derestrict( ~L ) ); + DerestrictTrait_ 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseMatrix& Q, DenseMatrix& 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_ > > + ql_backend( MT1& A, const ElementType_* 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_ > > + ql_backend( MT1& A, const ElementType_* 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 A( 32, 16 ); + // ... Initialization of A + + blaze::DynamicMatrix Q( 32, 16 ); + blaze::DynamicMatrix 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, or +// \c complex 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& A, DenseMatrix& Q, DenseMatrix& L ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT1 ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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_ ); + + typedef ElementType_ ET1; + + const size_t m( (~A).rows() ); + const size_t n( (~A).columns() ); + const size_t mindim( min( m, n ) ); + + if( ( !IsResizable::value && ( (~Q).rows() != m || (~Q).columns() != mindim ) ) || + ( !IsResizable::value && ( (~L).rows() != mindim || (~L).columns() != n ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Dimensions of fixed size matrix do not match" ); + } + + if( IsSquare::value && mindim != n ) { + BLAZE_THROW_INVALID_ARGUMENT( "Square matrix cannot be resized to min(m,n)-by-n" ); + } + + const std::unique_ptr tau( new ET1[mindim] ); + DerestrictTrait_ 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseMatrix& Q, DenseMatrix& 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_ > > + qr_backend( MT1& A, const ElementType_* 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_ > > + qr_backend( MT1& A, const ElementType_* 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 A( 32, 16 ); + // ... Initialization of A + + blaze::DynamicMatrix Q( 32, 16 ); + blaze::DynamicMatrix 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, or +// \c complex 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& A, DenseMatrix& Q, DenseMatrix& R ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT1 ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT2 ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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_ ); + + typedef ElementType_ ET1; + + const size_t m( (~A).rows() ); + const size_t n( (~A).columns() ); + const size_t mindim( min( m, n ) ); + + if( ( !IsResizable::value && ( (~Q).rows() != m || (~Q).columns() != mindim ) ) || + ( !IsResizable::value && ( (~R).rows() != mindim || (~R).columns() != n ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Dimensions of fixed size matrix do not match" ); + } + + if( IsSquare::value && mindim != n ) { + BLAZE_THROW_INVALID_ARGUMENT( "Square matrix cannot be resized to min(m,n)-by-n" ); + } + + const std::unique_ptr tau( new ET1[mindim] ); + DerestrictTrait_ 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseMatrix& R, DenseMatrix& 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_ > > + rq_backend( MT1& A, const ElementType_* 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_ > > + rq_backend( MT1& A, const ElementType_* 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 A( 32, 16 ); + // ... Initialization of A + + blaze::DynamicMatrix R( 32, 16 ); + blaze::DynamicMatrix 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, or +// \c complex 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& A, DenseMatrix& R, DenseMatrix& Q ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_STRICTLY_TRIANGULAR_MATRIX_TYPE( MT1 ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + 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_ ); + + BLAZE_CONSTRAINT_MUST_NOT_BE_ADAPTOR_TYPE( MT3 ); + BLAZE_CONSTRAINT_MUST_BE_BLAS_COMPATIBLE_TYPE( ElementType_ ); + + typedef ElementType_ ET1; + + const size_t m( (~A).rows() ); + const size_t n( (~A).columns() ); + const size_t mindim( min( m, n ) ); + + if( ( !IsResizable::value && ( (~R).rows() != m || (~R).columns() != mindim ) ) || + ( !IsResizable::value && ( (~Q).rows() != mindim || (~Q).columns() != n ) ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Dimensions of fixed size matrix do not match" ); + } + + if( IsSquare::value && m != mindim ) { + BLAZE_THROW_INVALID_ARGUMENT( "Square matrix cannot be resized to m-by-min(m,n)" ); + } + + const std::unique_ptr tau( new ET1[mindim] ); + DerestrictTrait_ r( derestrict( ~R ) ); + + if( m < n ) + { + (~Q) = A; + gerqf( ~Q, tau.get() ); + + resize( ~R, m, m ); + reset( r ); + + for( size_t i=0UL; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 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 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 C( 2, 3 ); // Empty row-major sparse single precision matrix + StaticMatrix D( 4.0F ); // Directly, homogeneously initialized single precision 3x2 matrix + + StaticMatrix E( A ); // Creation of a new row-major matrix as a copy of A + StaticMatrix 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, SO > +{ + public: + //**Type definitions**************************************************************************** + typedef StaticMatrix This; //!< Type of this StaticMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this StaticMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef StaticMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef StaticMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef Type ElementType; //!< Type of the matrix elements. + typedef SIMDTrait_ 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 Iterator; //!< Iterator over non-constant elements. + typedef DenseIterator 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 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::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 > 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& m ); + template< typename MT , bool SO2 > inline StaticMatrix( const Matrix& 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 > 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& rhs ); + template< typename MT , bool SO2 > inline StaticMatrix& operator= ( const Matrix& rhs ); + template< typename MT , bool SO2 > inline StaticMatrix& operator+=( const Matrix& rhs ); + template< typename MT , bool SO2 > inline StaticMatrix& operator-=( const Matrix& rhs ); + template< typename MT , bool SO2 > inline StaticMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_, StaticMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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_ >::value && + IsRowMajorMatrix::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_ >::value && + HasSIMDAdd< Type, ElementType_ >::value && + IsRowMajorMatrix::value && + !IsDiagonal::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_ >::value && + HasSIMDSub< Type, ElementType_ >::value && + IsRowMajorMatrix::value && + !IsDiagonal::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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_ > assign( const DenseMatrix& rhs ); + + template< typename MT, bool SO2 > + inline EnableIf_ > assign( const DenseMatrix& rhs ); + + template< typename MT > inline void assign( const SparseMatrix& rhs ); + template< typename MT > inline void assign( const SparseMatrix& rhs ); + + template< typename MT, bool SO2 > + inline DisableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT, bool SO2 > + inline EnableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + + template< typename MT, bool SO2 > + inline DisableIf_ > subAssign( const DenseMatrix& rhs ); + + template< typename MT, bool SO2 > + inline EnableIf_ > subAssign( const DenseMatrix& rhs ); + + template< typename MT > inline void subAssign( const SparseMatrix& rhs ); + template< typename MT > inline void subAssign( const SparseMatrix& 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, SizeT >::value ):( N ) }; + //********************************************************************************************** + + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + AlignedArray 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::StaticMatrix() + : v_() // The statically allocated matrix elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + if( IsNumeric::value ) { + for( size_t i=0UL; i // Storage order +inline StaticMatrix::StaticMatrix( const Type& init ) + : v_() // The statically allocated matrix elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + for( size_t i=0UL; i 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::StaticMatrix( initializer_list< initializer_list > list ) + : v_() // The statically allocated matrix elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::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 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::StaticMatrix( size_t m, size_t n, const Other* array ) + : v_() // The statically allocated matrix elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + if( m > M || n > N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static matrix" ); + } + + for( size_t i=0UL; i::value ) { + for( size_t j=n; j::value ) { + for( size_t i=m; i 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::StaticMatrix( const Other (&array)[M][N] ) + : v_() // The statically allocated matrix elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + for( size_t i=0UL; i // Storage order +inline StaticMatrix::StaticMatrix( const StaticMatrix& m ) + : v_() // The statically allocated matrix elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + for( size_t i=0UL; i // Storage order +template< typename Other // Data type of the foreign matrix + , bool SO2 > // Storage order of the foreign matrix +inline StaticMatrix::StaticMatrix( const StaticMatrix& m ) + : v_() // The statically allocated matrix elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + for( size_t i=0UL; i // Storage order +template< typename MT // Type of the foreign matrix + , bool SO2 > // Storage order of the foreign matrix +inline StaticMatrix::StaticMatrix( const Matrix& m ) + : v_() // The statically allocated matrix elements +{ + using blaze::assign; + + BLAZE_STATIC_ASSERT( IsVectorizable::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::value ? 0UL : N ); j // Storage order +inline typename StaticMatrix::Reference + StaticMatrix::operator()( size_t i, size_t j ) noexcept +{ + BLAZE_USER_ASSERT( i // Storage order +inline typename StaticMatrix::ConstReference + StaticMatrix::operator()( size_t i, size_t j ) const noexcept +{ + BLAZE_USER_ASSERT( i // Storage order +inline typename StaticMatrix::Reference + StaticMatrix::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::ConstReference + StaticMatrix::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::Pointer + StaticMatrix::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::ConstPointer + StaticMatrix::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::Pointer + StaticMatrix::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::ConstPointer + StaticMatrix::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::Iterator + StaticMatrix::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::ConstIterator + StaticMatrix::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::ConstIterator + StaticMatrix::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::Iterator + StaticMatrix::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::ConstIterator + StaticMatrix::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::ConstIterator + StaticMatrix::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& StaticMatrix::operator=( const Type& set ) +{ + for( size_t i=0UL; i 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& + StaticMatrix::operator=( initializer_list< initializer_list > 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 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& StaticMatrix::operator=( const Other (&array)[M][N] ) +{ + for( size_t i=0UL; i // Storage order +inline StaticMatrix& StaticMatrix::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& + StaticMatrix::operator=( const StaticMatrix& 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& StaticMatrix::operator=( const Matrix& rhs ) +{ + using blaze::assign; + + typedef TransExprTrait_ TT; + typedef CTransExprTrait_ CT; + typedef InvExprTrait_ IT; + + if( (~rhs).rows() != M || (~rhs).columns() != N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to static matrix" ); + } + + if( IsSame::value && (~rhs).isAliased( this ) ) { + transpose( typename IsSquare::Type() ); + } + else if( IsSame::value && (~rhs).isAliased( this ) ) { + ctranspose( typename IsSquare::Type() ); + } + else if( !IsSame::value && (~rhs).canAlias( this ) ) { + StaticMatrix tmp( ~rhs ); + assign( *this, tmp ); + } + else { + if( IsSparseMatrix::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& StaticMatrix::operator+=( const Matrix& 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_ 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& StaticMatrix::operator-=( const Matrix& 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_ 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& StaticMatrix::operator*=( const Matrix& 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_, StaticMatrix >& + StaticMatrix::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_, StaticMatrix >& + StaticMatrix::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::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::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::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::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::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::nonZeros() const +{ + size_t nonzeros( 0UL ); + + for( size_t i=0UL; i // Storage order +inline size_t StaticMatrix::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 // Storage order +inline void StaticMatrix::reset() +{ + using blaze::clear; + + for( size_t i=0UL; i // Storage order +inline void StaticMatrix::reset( size_t i ) +{ + using blaze::clear; + + BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" ); + for( size_t j=0UL; j // Storage order +inline StaticMatrix& StaticMatrix::transpose() +{ + using std::swap; + + BLAZE_STATIC_ASSERT( M == N ); + + for( size_t i=1UL; i 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::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 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::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& StaticMatrix::ctranspose() +{ + BLAZE_STATIC_ASSERT( M == N ); + + for( size_t i=0UL; i 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::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 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::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& StaticMatrix::scale( const Other& scalar ) +{ + for( size_t i=0UL; i // Storage order +inline void StaticMatrix::swap( StaticMatrix& m ) noexcept +{ + using std::swap; + + for( size_t i=0UL; i // Storage order +inline void* StaticMatrix::operator new( std::size_t size ) +{ + UNUSED_PARAMETER( size ); + + BLAZE_INTERNAL_ASSERT( size == sizeof( StaticMatrix ), "Invalid number of bytes detected" ); + + return allocate( 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::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( 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::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( 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::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( 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::operator delete( void* ptr ) +{ + deallocate( static_cast( 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::operator delete[]( void* ptr ) +{ + deallocate( static_cast( 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::operator delete( void* ptr, const std::nothrow_t& ) +{ + deallocate( static_cast( 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::operator delete[]( void* ptr, const std::nothrow_t& ) +{ + deallocate( static_cast( 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::isIntact() const noexcept +{ + if( IsNumeric::value ) { + for( size_t i=0UL; i // Storage order +template< typename Other > // Data type of the foreign expression +inline bool StaticMatrix::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::SIMDType + StaticMatrix::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::SIMDType + StaticMatrix::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::SIMDType + StaticMatrix::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::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::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::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::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_::BLAZE_TEMPLATE VectorizedAssign > + StaticMatrix::assign( const DenseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" ); + + for( size_t i=0UL; i // 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_::BLAZE_TEMPLATE VectorizedAssign > + StaticMatrix::assign( const DenseMatrix& 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::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 // Storage order +template< typename MT > // Type of the right-hand side sparse matrix +inline void StaticMatrix::assign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" ); + + for( size_t i=0UL; i 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::assign( const SparseMatrix& 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 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_::BLAZE_TEMPLATE VectorizedAddAssign > + StaticMatrix::addAssign( const DenseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" ); + + for( size_t i=0UL; i::value ) + { + v_[i*NN+i] += (~rhs)(i,i); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j // 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_::BLAZE_TEMPLATE VectorizedAddAssign > + StaticMatrix::addAssign( const DenseMatrix& 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::value ); + + for( size_t i=0UL; i::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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 // Storage order +template< typename MT > // Type of the right-hand side sparse matrix +inline void StaticMatrix::addAssign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" ); + + for( size_t i=0UL; i 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::addAssign( const SparseMatrix& 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 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_::BLAZE_TEMPLATE VectorizedSubAssign > + StaticMatrix::subAssign( const DenseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" ); + + for( size_t i=0UL; i::value ) + { + v_[i*NN+i] -= (~rhs)(i,i); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j // 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_::BLAZE_TEMPLATE VectorizedSubAssign > + StaticMatrix::subAssign( const DenseMatrix& 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::value ); + + for( size_t i=0UL; i::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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 // Storage order +template< typename MT > // Type of the right-hand side sparse matrix +inline void StaticMatrix::subAssign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" ); + + for( size_t i=0UL; i 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::subAssign( const SparseMatrix& 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 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 : public DenseMatrix< StaticMatrix, true > +{ + public: + //**Type definitions**************************************************************************** + typedef StaticMatrix This; //!< Type of this StaticMatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this StaticMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef StaticMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef StaticMatrix TransposeType; //!< Transpose type for expression template evaluations. + typedef Type ElementType; //!< Type of the matrix elements. + typedef SIMDTrait_ 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 Iterator; //!< Iterator over non-constant elements. + typedef DenseIterator 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 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::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 > 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& m ); + template< typename MT , bool SO > inline StaticMatrix( const Matrix& 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 > 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& rhs ); + template< typename MT , bool SO > inline StaticMatrix& operator= ( const Matrix& rhs ); + template< typename MT , bool SO > inline StaticMatrix& operator+=( const Matrix& rhs ); + template< typename MT , bool SO > inline StaticMatrix& operator-=( const Matrix& rhs ); + template< typename MT , bool SO > inline StaticMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_, StaticMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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_ >::value && + IsColumnMajorMatrix::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_ >::value && + HasSIMDAdd< Type, ElementType_ >::value && + IsColumnMajorMatrix::value && + !IsDiagonal::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_ >::value && + HasSIMDSub< Type, ElementType_ >::value && + IsColumnMajorMatrix::value && + !IsDiagonal::value }; + }; + //********************************************************************************************** + + //********************************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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_ > assign( const DenseMatrix& rhs ); + + template< typename MT, bool SO > + inline EnableIf_ > assign( const DenseMatrix& rhs ); + + template< typename MT > inline void assign( const SparseMatrix& rhs ); + template< typename MT > inline void assign( const SparseMatrix& rhs ); + + template< typename MT, bool SO > + inline DisableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT, bool SO > + inline EnableIf_ > addAssign( const DenseMatrix& rhs ); + + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT > inline void addAssign( const SparseMatrix& rhs ); + + template< typename MT, bool SO > + inline DisableIf_ > subAssign( const DenseMatrix& rhs ); + + template< typename MT, bool SO > + inline EnableIf_ > subAssign( const DenseMatrix& rhs ); + + template< typename MT > inline void subAssign( const SparseMatrix& rhs ); + template< typename MT > inline void subAssign( const SparseMatrix& 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, SizeT >::value ):( M ) }; + //********************************************************************************************** + + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + AlignedArray 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::StaticMatrix() + : v_() // The statically allocated matrix elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || MM == M ); + + if( IsNumeric::value ) { + for( size_t i=0UL; i // Number of columns +inline StaticMatrix::StaticMatrix( const Type& init ) + : v_() // The statically allocated matrix elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || MM == M ); + + for( size_t j=0UL; j 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::StaticMatrix( initializer_list< initializer_list > list ) + : v_() // The statically allocated matrix elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::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::value ) { + for( ; i 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::StaticMatrix( size_t m, size_t n, const Other* array ) + : v_() // The statically allocated matrix elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || MM == M ); + + if( m > M || n > N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static matrix" ); + } + + for( size_t j=0UL; j::value ) { + for( size_t i=m; i::value ) { + for( size_t j=n; j 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::StaticMatrix( const Other (&array)[M][N] ) + : v_() // The statically allocated matrix elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || MM == M ); + + for( size_t j=0UL; j // Number of columns +inline StaticMatrix::StaticMatrix( const StaticMatrix& m ) + : v_() // The statically allocated matrix elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || MM == M ); + + for( size_t i=0UL; i // Number of columns +template< typename Other // Data type of the foreign matrix + , bool SO > // Storage order of the foreign matrix +inline StaticMatrix::StaticMatrix( const StaticMatrix& m ) + : v_() // The statically allocated matrix elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || MM == M ); + + for( size_t j=0UL; j // Number of columns +template< typename MT // Type of the foreign matrix + , bool SO > // Storage order of the foreign matrix +inline StaticMatrix::StaticMatrix( const Matrix& m ) + : v_() // The statically allocated matrix elements +{ + using blaze::assign; + + BLAZE_STATIC_ASSERT( IsVectorizable::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::value ? 0UL : M ); i // Number of columns +inline typename StaticMatrix::Reference + StaticMatrix::operator()( size_t i, size_t j ) noexcept +{ + BLAZE_USER_ASSERT( i // Number of columns +inline typename StaticMatrix::ConstReference + StaticMatrix::operator()( size_t i, size_t j ) const noexcept +{ + BLAZE_USER_ASSERT( i // Number of columns +inline typename StaticMatrix::Reference + StaticMatrix::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::ConstReference + StaticMatrix::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::Pointer + StaticMatrix::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::ConstPointer + StaticMatrix::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::Pointer + StaticMatrix::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::ConstPointer + StaticMatrix::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::Iterator + StaticMatrix::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::ConstIterator + StaticMatrix::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::ConstIterator + StaticMatrix::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::Iterator + StaticMatrix::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::ConstIterator + StaticMatrix::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::ConstIterator + StaticMatrix::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& + StaticMatrix::operator=( const Type& set ) +{ + for( size_t j=0UL; j 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& + StaticMatrix::operator=( initializer_list< initializer_list > 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 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& + StaticMatrix::operator=( const Other (&array)[M][N] ) +{ + for( size_t j=0UL; j // Number of columns +inline StaticMatrix& + StaticMatrix::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& + StaticMatrix::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 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& StaticMatrix::operator=( const Matrix& rhs ) +{ + using blaze::assign; + + typedef TransExprTrait_ TT; + typedef CTransExprTrait_ CT; + typedef InvExprTrait_ IT; + + if( (~rhs).rows() != M || (~rhs).columns() != N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to static matrix" ); + } + + if( IsSame::value && (~rhs).isAliased( this ) ) { + transpose( typename IsSquare::Type() ); + } + else if( IsSame::value && (~rhs).isAliased( this ) ) { + ctranspose( typename IsSquare::Type() ); + } + else if( !IsSame::value && (~rhs).canAlias( this ) ) { + StaticMatrix tmp( ~rhs ); + assign( *this, tmp ); + } + else { + if( IsSparseMatrix::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& StaticMatrix::operator+=( const Matrix& 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_ 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& StaticMatrix::operator-=( const Matrix& 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_ 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& StaticMatrix::operator*=( const Matrix& 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_, StaticMatrix >& + StaticMatrix::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_, StaticMatrix >& + StaticMatrix::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::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::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::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::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::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::nonZeros() const +{ + size_t nonzeros( 0UL ); + + for( size_t j=0UL; j // Number of columns +inline size_t StaticMatrix::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 // Number of columns +inline void StaticMatrix::reset() +{ + using blaze::clear; + + for( size_t j=0UL; j // Number of columns +inline void StaticMatrix::reset( size_t j ) +{ + using blaze::clear; + + BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" ); + for( size_t i=0UL; i // Number of columns +inline StaticMatrix& StaticMatrix::transpose() +{ + using std::swap; + + BLAZE_STATIC_ASSERT( M == N ); + + for( size_t j=1UL; j 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::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 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::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& StaticMatrix::ctranspose() +{ + BLAZE_STATIC_ASSERT( M == N ); + + for( size_t j=0UL; j 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::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 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::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& + StaticMatrix::scale( const Other& scalar ) +{ + for( size_t j=0UL; j // Number of columns +inline void StaticMatrix::swap( StaticMatrix& m ) noexcept +{ + using std::swap; + + for( size_t j=0UL; j // Number of columns +inline void* StaticMatrix::operator new( std::size_t size ) +{ + UNUSED_PARAMETER( size ); + + BLAZE_INTERNAL_ASSERT( size == sizeof( StaticMatrix ), "Invalid number of bytes detected" ); + + return allocate( 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::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( 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::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( 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::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( 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::operator delete( void* ptr ) +{ + deallocate( static_cast( 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::operator delete[]( void* ptr ) +{ + deallocate( static_cast( 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::operator delete( void* ptr, const std::nothrow_t& ) +{ + deallocate( static_cast( 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::operator delete[]( void* ptr, const std::nothrow_t& ) +{ + deallocate( static_cast( 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::isIntact() const noexcept +{ + if( IsNumeric::value ) { + for( size_t j=0UL; j // Number of columns +template< typename Other > // Data type of the foreign expression +inline bool StaticMatrix::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::SIMDType + StaticMatrix::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::SIMDType + StaticMatrix::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::SIMDType + StaticMatrix::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::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::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::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::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_::BLAZE_TEMPLATE VectorizedAssign > + StaticMatrix::assign( const DenseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" ); + + for( size_t j=0UL; j // 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_::BLAZE_TEMPLATE VectorizedAssign > + StaticMatrix::assign( const DenseMatrix& 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::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 // Number of columns +template< typename MT > // Type of the right-hand side sparse matrix +inline void StaticMatrix::assign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" ); + + for( size_t j=0UL; j 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::assign( const SparseMatrix& 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 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_::BLAZE_TEMPLATE VectorizedAddAssign > + StaticMatrix::addAssign( const DenseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" ); + + for( size_t j=0UL; j::value ) + { + v_[j+j*MM] += (~rhs)(j,j); + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i // 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_::BLAZE_TEMPLATE VectorizedAddAssign > + StaticMatrix::addAssign( const DenseMatrix& 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::value ); + + for( size_t j=0UL; j::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Number of columns +template< typename MT > // Type of the right-hand side sparse matrix +inline void StaticMatrix::addAssign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" ); + + for( size_t j=0UL; j 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::addAssign( const SparseMatrix& 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 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_::BLAZE_TEMPLATE VectorizedSubAssign > + StaticMatrix::subAssign( const DenseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" ); + + for( size_t j=0UL; j::value ) + { + v_[j+j*MM] -= (~rhs)(j,j); + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i // 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_::BLAZE_TEMPLATE VectorizedSubAssign > + StaticMatrix::subAssign( const DenseMatrix& 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::value ); + + for( size_t j=0UL; j::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Number of columns +template< typename MT > // Type of the right-hand side sparse matrix +inline void StaticMatrix::subAssign( const SparseMatrix& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).rows() == M && (~rhs).columns() == N, "Invalid matrix size" ); + + for( size_t j=0UL; j 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::subAssign( const SparseMatrix& 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 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; +/*! \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; +/*! \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; +/*! \endcond */ +//************************************************************************************************* + + + + + + + + +//================================================================================================= +// +// STATICMATRIX OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name StaticMatrix operators */ +//@{ +template< typename Type, size_t M, size_t N, bool SO > +inline void reset( StaticMatrix& m ); + +template< typename Type, size_t M, size_t N, bool SO > +inline void reset( StaticMatrix& m, size_t i ); + +template< typename Type, size_t M, size_t N, bool SO > +inline void clear( StaticMatrix& m ); + +template< typename Type, size_t M, size_t N, bool SO > +inline bool isDefault( const StaticMatrix& m ); + +template< typename Type, size_t M, size_t N, bool SO > +inline bool isIntact( const StaticMatrix& m ) noexcept; + +template< typename Type, size_t M, size_t N, bool SO > +inline void swap( StaticMatrix& a, StaticMatrix& 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& 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& 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& 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 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& m ) +{ + if( SO == rowMajor ) { + for( size_t i=0UL; i 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& 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& a, StaticMatrix& b ) noexcept +{ + a.swap( b ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t M, size_t N, bool SO > +struct Rows< StaticMatrix > : public SizeT +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t M, size_t N, bool SO > +struct Columns< StaticMatrix > : public SizeT +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSQUARE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t N, bool SO > +struct IsSquare< StaticMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t M, size_t N, bool SO > +struct HasConstDataAccess< StaticMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t M, size_t N, bool SO > +struct HasMutableDataAccess< StaticMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t M, size_t N, bool SO > +struct IsAligned< StaticMatrix > : public BoolConstant +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t M, size_t N, bool SO > +struct IsPadded< StaticMatrix > : public BoolConstant +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ADDTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t M, size_t N, bool SO, typename T2 > +struct AddTrait< StaticMatrix, StaticMatrix > +{ + using Type = StaticMatrix< AddTrait_, M, N, SO >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 > +struct AddTrait< StaticMatrix, StaticMatrix > +{ + using Type = StaticMatrix< AddTrait_, 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, StaticMatrix > +{ + using Type = StaticMatrix< SubTrait_, M, N, SO >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 > +struct SubTrait< StaticMatrix, StaticMatrix > +{ + using Type = StaticMatrix< SubTrait_, 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, T2, EnableIf_ > > +{ + using Type = StaticMatrix< MultTrait_, M, N, SO >; +}; + +template< typename T1, typename T2, size_t M, size_t N, bool SO > +struct MultTrait< T1, StaticMatrix, EnableIf_ > > +{ + using Type = StaticMatrix< MultTrait_, M, N, SO >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2 > +struct MultTrait< StaticMatrix, StaticVector > +{ + using Type = StaticVector< MultTrait_, M, false >; +}; + +template< typename T1, size_t M, typename T2, size_t N, bool SO > +struct MultTrait< StaticVector, StaticMatrix > +{ + using Type = StaticVector< MultTrait_, N, true >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2, size_t L > +struct MultTrait< StaticMatrix, HybridVector > +{ + using Type = StaticVector< MultTrait_, M, false >; +}; + +template< typename T1, size_t L, typename T2, size_t M, size_t N, bool SO > +struct MultTrait< HybridVector, StaticMatrix > +{ + using Type = StaticVector< MultTrait_, N, true >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2 > +struct MultTrait< StaticMatrix, DynamicVector > +{ + using Type = StaticVector< MultTrait_, M, false >; +}; + +template< typename T1, typename T2, size_t M, size_t N, bool SO > +struct MultTrait< DynamicVector, StaticMatrix > +{ + using Type = StaticVector< MultTrait_, N, true >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2, bool AF, bool PF > +struct MultTrait< StaticMatrix, CustomVector > +{ + using Type = StaticVector< MultTrait_, M, false >; +}; + +template< typename T1, bool AF, bool PF, typename T2, size_t M, size_t N, bool SO > +struct MultTrait< CustomVector, StaticMatrix > +{ + using Type = StaticVector< MultTrait_, N, true >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2 > +struct MultTrait< StaticMatrix, CompressedVector > +{ + using Type = StaticVector< MultTrait_, M, false >; +}; + +template< typename T1, typename T2, size_t M, size_t N, bool SO > +struct MultTrait< CompressedVector, StaticMatrix > +{ + using Type = StaticVector< MultTrait_, N, true >; +}; + +template< typename T1, size_t M, size_t K, bool SO1, typename T2, size_t N, bool SO2 > +struct MultTrait< StaticMatrix, StaticMatrix > +{ + using Type = StaticMatrix< MultTrait_, 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, T2, EnableIf_ > > +{ + using Type = StaticMatrix< DivTrait_, 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, StaticMatrix > +{ + using HighType = StaticMatrix< typename MathTrait::HighType, M, N, SO >; + using LowType = StaticMatrix< typename MathTrait::LowType , M, N, SO >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t M, size_t N, bool SO > +struct SubmatrixTrait< StaticMatrix > +{ + using Type = HybridMatrix; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t M, size_t N, bool SO > +struct RowTrait< StaticMatrix > +{ + using Type = StaticVector; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t M, size_t N, bool SO > +struct ColumnTrait< StaticMatrix > +{ + using Type = StaticVector; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 a; // Default initialized 2D vector + a[0] = 1.0; // Initialization of the first element + a[1] = 2.0; // Initialization of the second element + + StaticVector b( 3.0, 2.0 ); // Directly initialized 2D vector + CompressedVector c( 2 ); // Empty sparse single precision vector + StaticVector d; // Default constructed static vector + StaticMatrix 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, TF > +{ + public: + //**Type definitions**************************************************************************** + typedef StaticVector This; //!< Type of this StaticVector instance. + typedef DenseVector BaseType; //!< Base type of this StaticVector instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef StaticVector TransposeType; //!< Transpose type for expression template evaluations. + typedef Type ElementType; //!< Type of the vector elements. + typedef SIMDTrait_ 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 Iterator; //!< Iterator over non-constant elements. + typedef DenseIterator 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 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::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 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& v ); + template< typename VT > inline StaticVector( const Vector& 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 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& rhs ); + + template< typename VT > inline StaticVector& operator= ( const Vector& rhs ); + template< typename VT > inline StaticVector& operator+=( const Vector& rhs ); + template< typename VT > inline StaticVector& operator-=( const Vector& rhs ); + template< typename VT > inline StaticVector& operator*=( const Vector& rhs ); + template< typename VT > inline StaticVector& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_, StaticVector >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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_ >::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_ >::value && + HasSIMDAdd< Type, ElementType_ >::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_ >::value && + HasSIMDSub< Type, ElementType_ >::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_ >::value && + HasSIMDMult< Type, ElementType_ >::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_ >::value && + HasSIMDDiv< Type, ElementType_ >::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + //! The number of elements packed within a single SIMD vector. + enum : size_t { SIMDSIZE = SIMDTrait::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 > assign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > assign( const DenseVector& rhs ); + + template< typename VT > inline void assign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > addAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > addAssign( const DenseVector& rhs ); + + template< typename VT > inline void addAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > subAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > subAssign( const DenseVector& rhs ); + + template< typename VT > inline void subAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > multAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > multAssign( const DenseVector& rhs ); + + template< typename VT > inline void multAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_ > divAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_ > divAssign( const DenseVector& rhs ); + //@} + //********************************************************************************************** + + private: + //********************************************************************************************** + //! Alignment adjustment. + enum : size_t { NN = ( usePadding )?( NextMultiple< SizeT, SizeT >::value ):( N ) }; + //********************************************************************************************** + + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + AlignedArray 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::StaticVector() + : v_() // The statically allocated vector elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + if( IsNumeric::value ) { + for( size_t i=0UL; i // Transpose flag +inline StaticVector::StaticVector( const Type& init ) + : v_() // The statically allocated vector elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + for( size_t i=0UL; i 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::StaticVector( initializer_list list ) + : v_() // The statically allocated vector elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::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 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::StaticVector( size_t n, const Other* array ) + : v_() // The statically allocated vector elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + if( n > N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static vector" ); + } + + for( size_t i=0UL; i::value ) { + for( size_t i=n; i 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::StaticVector( const Other (&array)[N] ) + : v_() // The statically allocated vector elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + for( size_t i=0UL; i // Transpose flag +inline StaticVector::StaticVector( const StaticVector& v ) + : v_() // The statically allocated vector elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + for( size_t i=0UL; i // Transpose flag +template< typename Other > // Data type of the foreign vector +inline StaticVector::StaticVector( const StaticVector& v ) + : v_() // The statically allocated vector elements +{ + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + for( size_t i=0UL; i // Transpose flag +template< typename VT > // Type of the foreign vector +inline StaticVector::StaticVector( const Vector& v ) + : v_() // The statically allocated vector elements +{ + using blaze::assign; + + BLAZE_STATIC_ASSERT( IsVectorizable::value || NN == N ); + + if( (~v).size() != N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid setup of static vector" ); + } + + for( size_t i=( IsSparseVector::value ? 0UL : N ); i // Transpose flag +inline typename StaticVector::Reference + StaticVector::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::ConstReference + StaticVector::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::Reference + StaticVector::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::ConstReference + StaticVector::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::Pointer StaticVector::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::ConstPointer StaticVector::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::Iterator StaticVector::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::ConstIterator StaticVector::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::ConstIterator StaticVector::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::Iterator StaticVector::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::ConstIterator StaticVector::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::ConstIterator StaticVector::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& StaticVector::operator=( const Type& rhs ) +{ + for( size_t i=0UL; i 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& StaticVector::operator=( initializer_list 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 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& StaticVector::operator=( const Other (&array)[N] ) +{ + for( size_t i=0UL; i // Transpose flag +inline StaticVector& StaticVector::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& StaticVector::operator=( const StaticVector& 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& StaticVector::operator=( const Vector& 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::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& StaticVector::operator+=( const Vector& 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& StaticVector::operator-=( const Vector& 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& StaticVector::operator*=( const Vector& rhs ) +{ + using blaze::multAssign; + + if( (~rhs).size() != N ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + if( IsSparseVector::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& StaticVector::operator/=( const DenseVector& 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_, StaticVector >& + StaticVector::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_, StaticVector >& + StaticVector::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::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::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::nonZeros() const +{ + size_t nonzeros( 0 ); + + for( size_t i=0UL; i // Transpose flag +inline void StaticVector::reset() +{ + using blaze::clear; + for( size_t i=0UL; i // Transpose flag +template< typename Other > // Data type of the scalar value +inline StaticVector& StaticVector::scale( const Other& scalar ) +{ + for( size_t i=0; i // Transpose flag +inline void StaticVector::swap( StaticVector& v ) noexcept +{ + using std::swap; + + for( size_t i=0UL; i // Transpose flag +inline void* StaticVector::operator new( std::size_t size ) +{ + UNUSED_PARAMETER( size ); + + BLAZE_INTERNAL_ASSERT( size == sizeof( StaticVector ), "Invalid number of bytes detected" ); + + return allocate( 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::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( 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::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( 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::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( 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::operator delete( void* ptr ) +{ + deallocate( static_cast( 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::operator delete[]( void* ptr ) +{ + deallocate( static_cast( 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::operator delete( void* ptr, const std::nothrow_t& ) +{ + deallocate( static_cast( 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::operator delete[]( void* ptr, const std::nothrow_t& ) +{ + deallocate( static_cast( 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::isIntact() const noexcept +{ + if( IsNumeric::value ) { + for( size_t i=N; i // Transpose flag +template< typename Other > // Data type of the foreign expression +inline bool StaticVector::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::SIMDType + StaticVector::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::SIMDType + StaticVector::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::SIMDType + StaticVector::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::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::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::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::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_::BLAZE_TEMPLATE VectorizedAssign > + StaticVector::assign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" ); + + for( size_t i=0UL; i // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedAssign > + StaticVector::assign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" ); + + const bool remainder( !usePadding || !IsPadded::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 // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void StaticVector::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedAddAssign > + StaticVector::addAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" ); + + for( size_t i=0UL; i // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedAddAssign > + StaticVector::addAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" ); + + const bool remainder( !usePadding || !IsPadded::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 // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void StaticVector::addAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedSubAssign > + StaticVector::subAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" ); + + for( size_t i=0UL; i // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedSubAssign > + StaticVector::subAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" ); + + const bool remainder( !usePadding || !IsPadded::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 // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void StaticVector::subAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" ); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedMultAssign > + StaticVector::multAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" ); + + for( size_t i=0UL; i // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedMultAssign > + StaticVector::multAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( Type ); + + BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" ); + + const bool remainder( !usePadding || !IsPadded::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 // Transpose flag +template< typename VT > // Type of the right-hand side sparse vector +inline void StaticVector::multAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" ); + + const StaticVector tmp( serial( *this ) ); + + reset(); + + for( ConstIterator_ 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_::BLAZE_TEMPLATE VectorizedDivAssign > + StaticVector::divAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( (~rhs).size() == N, "Invalid vector sizes" ); + + for( size_t i=0UL; i // Transpose flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_::BLAZE_TEMPLATE VectorizedDivAssign > + StaticVector::divAssign( const DenseVector& 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 // Transpose flag +class StaticVector; +/*! \endcond */ +//************************************************************************************************* + + + + + + + + +//================================================================================================= +// +// STATICVECTOR OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name StaticVector operators */ +//@{ +template< typename Type, size_t N, bool TF > +inline void reset( StaticVector& v ); + +template< typename Type, size_t N, bool TF > +inline void clear( StaticVector& v ); + +template< typename Type, size_t N, bool TF > +inline bool isDefault( const StaticVector& v ); + +template< typename Type, size_t N, bool TF > +inline bool isIntact( const StaticVector& v ) noexcept; + +template< typename Type, bool TF > +inline const StaticVector perp( const StaticVector& v ); + +template< typename Type, bool TF > +inline const StaticVector perp( const StaticVector& v ); + +template< typename Type, size_t N, bool TF > +inline void swap( StaticVector& a, StaticVector& 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& 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& 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 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& v ) +{ + for( size_t i=0UL; i 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& 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 perp( const StaticVector& v ) +{ + return StaticVector( -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 perp( const StaticVector& v ) +{ + if( v[0] != Type() || v[1] != Type() ) + return StaticVector( v[1UL], -v[0UL], Type() ); + else + return StaticVector( 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& a, StaticVector& b ) noexcept +{ + a.swap( b ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t N, bool TF > +struct Size< StaticVector > +{ + static const size_t value = N; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t N, bool TF > +struct HasConstDataAccess< StaticVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t N, bool TF > +struct HasMutableDataAccess< StaticVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t N, bool TF > +struct IsAligned< StaticVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, size_t N, bool TF > +struct IsPadded< StaticVector > : public BoolConstant +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ADDTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t N, bool TF, typename T2 > +struct AddTrait< StaticVector, StaticVector > +{ + using Type = StaticVector< AddTrait_, N, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t N, bool TF, typename T2 > +struct SubTrait< StaticVector, StaticVector > +{ + using Type = StaticVector< SubTrait_, N, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t N, bool TF, typename T2 > +struct MultTrait< StaticVector, T2, EnableIf_ > > +{ + using Type = StaticVector< MultTrait_, N, TF >; +}; + +template< typename T1, typename T2, size_t N, bool TF > +struct MultTrait< T1, StaticVector, EnableIf_ > > +{ + using Type = StaticVector< MultTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct MultTrait< StaticVector, StaticVector > +{ + using Type = StaticVector< MultTrait_, N, TF >; +}; + +template< typename T1, size_t M, typename T2, size_t N > +struct MultTrait< StaticVector, StaticVector > +{ + using Type = StaticMatrix< MultTrait_, M, N, false >; +}; + +template< typename T1, size_t N, typename T2 > +struct MultTrait< StaticVector, StaticVector > +{ + using Type = MultTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// CROSSTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, typename T2, bool TF > +struct CrossTrait< StaticVector, StaticVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t N, bool TF, typename T2 > +struct DivTrait< StaticVector, T2, EnableIf_ > > +{ + using Type = StaticVector< DivTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct DivTrait< StaticVector, StaticVector > +{ + using Type = StaticVector< DivTrait_, N, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MATHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t N, bool TF, typename T2 > +struct MathTrait< StaticVector, StaticVector > +{ + using HighType = StaticVector< typename MathTrait::HighType, N, TF >; + using LowType = StaticVector< typename MathTrait::LowType , N, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTORTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, size_t N, bool TF > +struct SubvectorTrait< StaticVector > +{ + using Type = HybridVector; +}; +/*! \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 + + +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 + + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatMatAddExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense matrix expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side dense matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef AddExprTrait_ 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::value || RequiresEvaluation::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 This; //!< Type of this DMatDMatAdd instance. + typedef AddTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side dense matrix expression. + typedef If_< IsExpression, 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_ LeftIteratorType; + + //! ConstIterator type of the right-hand side dense matrix expression. + typedef ConstIterator_ 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::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::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::value && ( RequiresEvaluation::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) || + ( IsExpression::value && ( RequiresEvaluation::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 > + assign( DenseMatrix& 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::value && isSame( ~lhs, rhs.lhs_ ) ) { + addAssign( ~lhs, rhs.rhs_ ); + } + else if( !IsExpression::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 > + assign( SparseMatrix& 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_ ); + + 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 > + addAssign( DenseMatrix& 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 > + subAssign( DenseMatrix& 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 > + smpAssign( DenseMatrix& 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::value && isSame( ~lhs, rhs.lhs_ ) ) { + smpAddAssign( ~lhs, rhs.rhs_ ); + } + else if( !IsExpression::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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 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 + operator+( const DenseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatDMatAddExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct Rows< DMatDMatAddExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct Columns< DMatDMatAddExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsAligned< DMatDMatAddExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsPadded< DMatDMatAddExpr > + : public BoolConstant< And< IsPadded, IsPadded >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsSymmetric< DMatDMatAddExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsHermitian< DMatDMatAddExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsLower< DMatDMatAddExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUniLower< DMatDMatAddExpr > + : public BoolConstant< Or< And< IsUniLower, IsStrictlyLower > + , And< IsUniLower, IsStrictlyLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsStrictlyLower< DMatDMatAddExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUpper< DMatDMatAddExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUniUpper< DMatDMatAddExpr > + : public BoolConstant< Or< And< IsUniUpper, IsStrictlyUpper > + , And< IsUniUpper, IsStrictlyUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsStrictlyUpper< DMatDMatAddExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO, bool AF > +struct SubmatrixExprTrait< DMatDMatAddExpr, AF > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct RowExprTrait< DMatDMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct ColumnExprTrait< DMatDMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side dense matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::value && + ( IsSymmetric::value || IsSymmetric::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::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::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::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DMatDMatMultExpr This; //!< Type of this DMatDMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side dense matrix expression. + typedef If_< IsExpression, 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::value && + MT1::simdEnabled && MT2::simdEnabled && + HasSIMDAdd::value && + HasSIMDMult::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::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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 > + assign( DenseMatrix& 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::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 >, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + if( IsStrictlyTriangular::value && kbegin == kend ) { + for( size_t j=0UL; j::value ) + ?( IsStrictlyUpper::value ? kbegin+1UL : kbegin ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? kbegin : kbegin+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + if( IsUpper::value && IsUpper::value ) { + for( size_t j=0UL; j::value ) { + reset( C(i,0UL) ); + } + for( size_t j=jbegin; j::value && IsLower::value ) { + for( size_t j=jend; j::value ) { + reset( C(i,N-1UL) ); + } + } + + for( size_t k=kbegin+1UL; k::value ) + ?( IsStrictlyUpper::value ? k+1UL : k ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? k-1UL : k ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j::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 >, IsDiagonal > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + if( IsUpper::value ) { + for( size_t j=0UL; j::value ) { + for( size_t j=jend; j // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + if( IsUpper::value ) { + for( size_t j=0UL; j::value ) { + for( size_t j=jend; j // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + 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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallAssignKernel( DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_ ); + + if( !IsResizable::value && IsResizable::value ) { + const OppositeType_ tmp( serial( A ) ); + assign( ~C, tmp * B ); + } + else if( IsResizable::value && !IsResizable::value ) { + const OppositeType_ tmp( serial( B ) ); + assign( ~C, A * tmp ); + } + else if( A.rows() * A.columns() <= B.rows() * B.columns() ) { + const OppositeType_ tmp( serial( A ) ); + assign( ~C, tmp * B ); + } + else { + const OppositeType_ 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 > + 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 > + selectLargeAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + for( size_t jj=0UL; jj::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+4UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectLargeAssignKernel( DenseMatrix& 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 > + 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 > + selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( C, B ); + trmm( C, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(1) ); + } + else if( IsTriangular::value ) { + assign( C, A ); + trmm( C, B, CblasRight, ( IsLower::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 > + assign( SparseMatrix& 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_ ); + + 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 > + assign( Matrix& 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::value && IsSymmetric::value ) + assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + addAssign( DenseMatrix& 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::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 >, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + for( size_t k=kbegin; k::value ) + ?( IsStrictlyUpper::value ? k+1UL : k ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 ); + + for( size_t i=0UL; i // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAddAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + ElementType value1( (~C)(i ,j) ); + ElementType value2( (~C)(i+1UL,j) );; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallAddAssignKernel( DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_ ); + + if( !IsResizable::value && IsResizable::value ) { + const OppositeType_ tmp( serial( A ) ); + addAssign( ~C, tmp * B ); + } + else if( IsResizable::value && !IsResizable::value ) { + const OppositeType_ tmp( serial( B ) ); + addAssign( ~C, A * tmp ); + } + else if( A.rows() * A.columns() <= B.rows() * B.columns() ) { + const OppositeType_ tmp( serial( A ) ); + addAssign( ~C, tmp * B ); + } + else { + const OppositeType_ 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 > + 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 > + selectLargeAddAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + for( size_t jj=0UL; jj::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+4UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectLargeAddAssignKernel( DenseMatrix& 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 > + 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 > + selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(1) ); + addAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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 > + addAssign( Matrix& 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::value && IsSymmetric::value ) + addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + subAssign( DenseMatrix& 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::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 >, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + for( size_t k=kbegin; k::value ) + ?( IsStrictlyUpper::value ? k+1UL : k ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( MT3 ); + + for( size_t i=0UL; i // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallSubAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + ElementType value1( (~C)(i ,j) ); + ElementType value2( (~C)(i+1UL,j) ); + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallSubAssignKernel( DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_ ); + + if( !IsResizable::value && IsResizable::value ) { + const OppositeType_ tmp( serial( A ) ); + subAssign( ~C, tmp * B ); + } + else if( IsResizable::value && !IsResizable::value ) { + const OppositeType_ tmp( serial( B ) ); + subAssign( ~C, A * tmp ); + } + else if( A.rows() * A.columns() <= B.rows() * B.columns() ) { + const OppositeType_ tmp( serial( A ) ); + subAssign( ~C, tmp * B ); + } + else { + const OppositeType_ 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 > + 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 > + selectLargeSubAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + for( size_t jj=0UL; jj::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+4UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectLargeSubAssignKernel( DenseMatrix& 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 > + 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 > + selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(1) ); + subAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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 > + subAssign( Matrix& 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::value && IsSymmetric::value ) + subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAssign( Matrix& 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::value && IsSymmetric::value ) + smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + smpAddAssign( DenseMatrix& 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 > + smpAddAssign( Matrix& 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::value && IsSymmetric::value ) + smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + smpSubAssign( DenseMatrix& 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 > + smpSubAssign( Matrix& 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::value && IsSymmetric::value ) + smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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, ST, false > + : public DenseMatrix< DMatScalarMultExpr< DMatDMatMultExpr, ST, false >, false > + , private MatScalarMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef DMatDMatMultExpr MMM; //!< Type of the dense matrix multiplication expression. + typedef ResultType_ RES; //!< Result type of the dense matrix multiplication expression. + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side dense matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::value && + ( IsSymmetric::value || IsSymmetric::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::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + !( IsBuiltin< ElementType_ >::value && IsComplex::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::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ + , T4 >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DMatScalarMultExpr This; //!< Type of this DMatScalarMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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 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::value && + MT1::simdEnabled && MT2::simdEnabled && + AreSIMDCombinable::value && + HasSIMDAdd::value && + HasSIMDMult::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::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_ 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 > + assign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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::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 >, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + if( IsStrictlyTriangular::value && kbegin == kend ) { + for( size_t j=0UL; j::value ) + ?( IsStrictlyUpper::value ? kbegin+1UL : kbegin ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? kbegin : kbegin+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + if( IsUpper::value && IsUpper::value ) { + for( size_t j=0UL; j::value ) { + reset( C(i,0UL) ); + } + for( size_t j=jbegin; j::value && IsLower::value ) { + for( size_t j=jend; j::value ) { + reset( C(i,N-1UL) ); + } + } + + for( size_t k=kbegin+1UL; k::value ) + ?( IsStrictlyUpper::value ? k+1UL : k ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? k-1UL : k ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j::value ) { + C(i,jend) = A(i,k) * B(k,jend); + } + } + + { + const size_t jbegin( ( IsUpper::value && IsUpper::value ) + ?( IsStrictlyUpper::value || IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value && IsLower::value ) + ?( IsStrictlyLower::value || IsStrictlyLower::value ? i : i+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j // Type of the scalar value + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + if( IsUpper::value ) { + for( size_t j=0UL; j::value ) { + for( size_t j=jend; j // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + if( IsUpper::value ) { + for( size_t j=0UL; j::value ) { + for( size_t j=jend; j // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + 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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallAssignKernel( DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_ ); + + if( !IsResizable::value && IsResizable::value ) { + const OppositeType_ tmp( serial( A ) ); + assign( ~C, tmp * B * scalar ); + } + else if( IsResizable::value && !IsResizable::value ) { + const OppositeType_ tmp( serial( B ) ); + assign( ~C, A * tmp * scalar ); + } + else if( A.rows() * A.columns() <= B.rows() * B.columns() ) { + const OppositeType_ tmp( serial( A ) ); + assign( ~C, tmp * B * scalar ); + } + else { + const OppositeType_ 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 > + 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 > + selectLargeAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + const SIMDType factor( set( scalar ) ); + + for( size_t jj=0UL; jj::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+4UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectLargeAssignKernel( DenseMatrix& 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 > + 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 > + selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( C, B ); + trmm( C, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(scalar) ); + } + else if( IsTriangular::value ) { + assign( C, A ); + trmm( C, B, CblasRight, ( IsLower::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 > + assign( SparseMatrix& 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_ ); + + 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 > + assign( Matrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ right( rhs.matrix_.rightOperand() ); + + if( IsSymmetric::value && IsSymmetric::value ) + assign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ ); + else if( IsSymmetric::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 > + addAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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::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 >, Not< IsDiagonal > > > + 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 >, IsDiagonal > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + 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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAddAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallAddAssignKernel( DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_ ); + + if( !IsResizable::value && IsResizable::value ) { + const OppositeType_ tmp( serial( A ) ); + addAssign( ~C, tmp * B * scalar ); + } + else if( IsResizable::value && !IsResizable::value ) { + const OppositeType_ tmp( serial( B ) ); + addAssign( ~C, A * tmp * scalar ); + } + else if( A.rows() * A.columns() <= B.rows() * B.columns() ) { + const OppositeType_ tmp( serial( A ) ); + addAssign( ~C, tmp * B * scalar ); + } + else { + const OppositeType_ 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 > + 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 > + selectLargeAddAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + const SIMDType factor( set( scalar ) ); + + for( size_t jj=0UL; jj::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+4UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectLargeAddAssignKernel( DenseMatrix& 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 > + 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 > + selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(scalar) ); + addAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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 > + addAssign( Matrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ right( rhs.matrix_.rightOperand() ); + + if( IsSymmetric::value && IsSymmetric::value ) + addAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ ); + else if( IsSymmetric::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 > + subAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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::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 >, Not< IsDiagonal > > > + 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 >, IsDiagonal > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + 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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallSubAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallSubAssignKernel( DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_ ); + + if( !IsResizable::value && IsResizable::value ) { + const OppositeType_ tmp( serial( A ) ); + subAssign( ~C, tmp * B * scalar ); + } + else if( IsResizable::value && !IsResizable::value ) { + const OppositeType_ tmp( serial( B ) ); + subAssign( ~C, A * tmp * scalar ); + } + else if( A.rows() * A.columns() <= B.rows() * B.columns() ) { + const OppositeType_ tmp( serial( A ) ); + subAssign( ~C, tmp * B * scalar ); + } + else { + const OppositeType_ 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 > + 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 > + selectLargeSubAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + const SIMDType factor( set( scalar ) ); + + for( size_t jj=0UL; jj::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+4UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectLargeSubAssignKernel( DenseMatrix& 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 > + 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 > + selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(scalar) ); + subAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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 > + subAssign( Matrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ right( rhs.matrix_.rightOperand() ); + + if( IsSymmetric::value && IsSymmetric::value ) + subAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ ); + else if( IsSymmetric::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 > + smpAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAssign( Matrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ right( rhs.matrix_.rightOperand() ); + + if( IsSymmetric::value && IsSymmetric::value ) + smpAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ ); + else if( IsSymmetric::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 > + smpAddAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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 > + smpAddAssign( Matrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ right( rhs.matrix_.rightOperand() ); + + if( IsSymmetric::value && IsSymmetric::value ) + smpAddAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ ); + else if( IsSymmetric::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 > + smpSubAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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 > + smpSubAssign( Matrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ right( rhs.matrix_.rightOperand() ); + + if( IsSymmetric::value && IsSymmetric::value ) + smpSubAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ ); + else if( IsSymmetric::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 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 + operator*( const DenseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatDMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< DMatDMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< DMatDMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsAligned< DMatDMatMultExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< DMatDMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< DMatDMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< DMatDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< DMatDMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< DMatDMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< DMatDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct DMatDVecMultExprTrait< DMatDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseVector, IsColumnVector > + , DMatDVecMultExprTrait_< MT1, DMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct DMatSVecMultExprTrait< DMatDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsSparseVector, IsColumnVector > + , DMatDVecMultExprTrait_< MT1, DMatSVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecDMatMultExprTrait< VT, DMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , TDVecDMatMultExprTrait_< TDVecDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecDMatMultExprTrait< VT, DMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , TDVecDMatMultExprTrait_< TSVecDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< DMatDMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< DMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< DMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatMatSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense matrix expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side dense matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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::value || RequiresEvaluation::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 This; //!< Type of this DMatDMatSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side dense matrix expression. + typedef If_< IsExpression, 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_ LeftIteratorType; + + //! ConstIterator type of the right-hand side dense matrix expression. + typedef ConstIterator_ 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::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::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::value && ( RequiresEvaluation::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) || + ( IsExpression::value && ( RequiresEvaluation::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 > + assign( DenseMatrix& 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::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 > + assign( SparseMatrix& 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_ ); + + 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 > + addAssign( DenseMatrix& 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 > + subAssign( DenseMatrix& 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 > + smpAssign( DenseMatrix& 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::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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 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 + operator-( const DenseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatDMatSubExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct Rows< DMatDMatSubExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct Columns< DMatDMatSubExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsAligned< DMatDMatSubExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsPadded< DMatDMatSubExpr > + : public BoolConstant< And< IsPadded, IsPadded >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsSymmetric< DMatDMatSubExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsHermitian< DMatDMatSubExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsLower< DMatDMatSubExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUniLower< DMatDMatSubExpr > + : public BoolConstant< And< IsUniLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsStrictlyLower< DMatDMatSubExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUpper< DMatDMatSubExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUniUpper< DMatDMatSubExpr > + : public BoolConstant< And< IsUniUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsStrictlyUpper< DMatDMatSubExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO, bool AF > +struct SubmatrixExprTrait< DMatDMatSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct RowExprTrait< DMatDMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct ColumnExprTrait< DMatDMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ MRT; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ VRT; //!< Result type of the right-hand side dense vector expression. + typedef ElementType_ MET; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ VET; //!< Element type of the right-hand side dense vector expression. + typedef CompositeType_ MCT; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value && IsSame::value && + IsBLASCompatible::value ) || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense vector expression. + enum : bool { evaluateVector = IsComputation::value || RequiresEvaluation::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::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::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DMatDVecMultExpr This; //!< Type of this DMatDVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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, const MT, const MT& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, 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::value && + MT::simdEnabled && VT::simdEnabled && + HasSIMDAdd::value && + HasSIMDMult::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::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::value ) + { + return mat_(index,index) * vec_[index]; + } + else if( IsLower::value && ( index + 8UL < mat_.rows() ) ) + { + const size_t n( IsStrictlyLower::value ? index : index+1UL ); + return subvector( row( mat_, index ), 0UL, n ) * subvector( vec_, 0UL, n ); + } + else if( IsUpper::value && ( index > 8UL ) ) + { + const size_t begin( IsStrictlyUpper::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::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& 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::value ); + + size_t i( 0UL ); + + for( ; (i+8UL) <= M; i+=8UL ) + { + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side vector operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::value ); + + reset( y ); + + size_t i( 0UL ); + + for( ; (i+8UL) <= M; i+=8UL ) + { + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side vector operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( y, x ); + trmv( y, A, ( IsLower::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& 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_ ); + + 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& 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::value ); + + size_t i( 0UL ); + + for( ; (i+8UL) <= M; i+=8UL ) + { + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side vector operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::value ); + + size_t i( 0UL ); + + for( ; (i+8UL) <= M; i+=8UL ) + { + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side vector operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( x ) ); + trmv( tmp, A, ( IsLower::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& 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::value ); + + size_t i( 0UL ); + + for( ; (i+8UL) <= M; i+=8UL ) + { + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side vector operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::value ); + + size_t i( 0UL ); + + for( ; (i+8UL) <= M; i+=8UL ) + { + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side vector operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( x ) ); + trmv( tmp, A, ( IsLower::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& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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, ST, false > + : public DenseVector< DVecScalarMultExpr< DMatDVecMultExpr, ST, false >, false > + , private VecScalarMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef DMatDVecMultExpr MVM; //!< Type of the dense matrix-dense vector multiplication expression. + typedef ResultType_ RES; //!< Result type of the dense matrix-dense vector multiplication expression. + typedef ResultType_ MRT; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ VRT; //!< Result type of the right-hand side dense vector expression. + typedef ElementType_ MET; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ VET; //!< Element type of the right-hand side dense vector expression. + typedef CompositeType_ MCT; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value && IsSame::value && + IsBLASCompatible::value ) || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense vector expression. + enum : bool { evaluateVector = IsComputation::value || RequiresEvaluation::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + !( IsBuiltin< ElementType_ >::value && IsComplex::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::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ + , T4 >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DVecScalarMultExpr This; //!< Type of this DVecScalarMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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 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::value && + MT::simdEnabled && VT::simdEnabled && + AreSIMDCombinable::value && + HasSIMDAdd::value && + HasSIMDMult::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::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_ A( vector_.leftOperand() ); + return ( !BLAZE_BLAS_IS_PARALLEL || + ( IsComputation::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& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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::value ) || + ( IsComputation::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 > + 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 > + 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 > + 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::value || !IsPadded::value ); + + size_t i( 0UL ); + + for( ; (i+8UL) <= M; i+=8UL ) + { + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::value ); + + reset( y ); + + size_t i( 0UL ); + + for( ; (i+8UL) <= M; i+=8UL ) + { + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( y, scalar * x ); + trmv( y, A, ( IsLower::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& 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_ ); + + 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& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::value ); + + size_t i( 0UL ); + + for( ; (i+8UL) <= M; i+=8UL ) + { + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::value ); + + size_t i( 0UL ); + + for( ; (i+8UL) <= M; i+=8UL ) + { + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( scalar * x ) ); + trmv( tmp, A, ( IsLower::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& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::value ); + + size_t i( 0UL ); + + for( ; (i+8UL) <= M; i+=8UL ) + { + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::value ); + + size_t i( 0UL ); + + for( ; (i+8UL) <= M; i+=8UL ) + { + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( scalar * x ) ); + trmv( tmp, A, ( IsLower::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& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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 > + smpSubAssign( DenseVector& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 A; + blaze::DynamicVector 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, DMatDVecMultExpr > + operator*( const DenseMatrix& mat, const DenseVector& vec ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~mat).columns() != (~vec).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" ); + } + + return DMatDVecMultExpr( ~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, MultExprTrait_ > + operator*( const DenseMatrix& mat, const DenseVector& 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 > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT > +struct IsAligned< DMatDVecMultExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, bool AF > +struct SubvectorExprTrait< DMatDVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// DETERMINANT FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Determinant functions */ +//@{ +template< typename MT, bool SO > +inline ElementType_ det( const DenseMatrix& 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_ det2x2( const DenseMatrix& dm ) +{ + BLAZE_INTERNAL_ASSERT( (~dm).rows() == 2UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( (~dm).columns() == 2UL, "Invalid number of columns detected" ); + + CompositeType_ 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_ det3x3( const DenseMatrix& dm ) +{ + BLAZE_INTERNAL_ASSERT( (~dm).rows() == 3UL, "Invalid number of rows detected" ); + BLAZE_INTERNAL_ASSERT( (~dm).columns() == 3UL, "Invalid number of columns detected" ); + + CompositeType_ 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_ det4x4( const DenseMatrix& 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_ ET; + + CompositeType_ 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_ det5x5( const DenseMatrix& 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_ ET; + + CompositeType_ 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_ det6x6( const DenseMatrix& 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_ ET; + + CompositeType_ 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_ detNxN( const DenseMatrix& dm ) +{ + BLAZE_INTERNAL_ASSERT( isSquare( ~dm ), "Non-square symmetric matrix detected" ); + + typedef ResultType_ RT; + typedef ElementType_ ET; + typedef RemoveAdaptor_ 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( A.rows() ) ); + int lda ( boost::numeric_cast( A.spacing() ) ); + int info( 0 ); + + const std::unique_ptr 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 // Storage order of the dense matrix +inline ElementType_ det( const DenseMatrix& dm ) +{ + typedef ElementType_ ET; + + if( !isSquare( ~dm ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" ); + } + + const size_t N( (~dm).rows() ); + + if( IsStrictlyTriangular::value || N == 0UL ) { + return ET(0); + } + + if( IsUniTriangular::value ) { + return ET(1); + } + + if( N == 1UL ) { + return (~dm)(0,0); + } + + if( IsTriangular::value ) { + ET determinant( (~dm)(0,0) ); + + for( size_t i=1UL; i +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatEvalExpr + , private Computation +{ + public: + //**Type definitions**************************************************************************** + typedef DMatEvalExpr This; //!< Type of this DMatEvalExpr instance. + typedef ResultType_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ 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, 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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 A, B; + // ... Resizing and initialization + B = eval( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatEvalExpr eval( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatEvalExpr( ~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 eval( const DMatEvalExpr& dm ) +{ + return dm; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct Rows< DMatEvalExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct Columns< DMatEvalExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsAligned< DMatEvalExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsSymmetric< DMatEvalExpr > + : public BoolConstant< IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsHermitian< DMatEvalExpr > + : public BoolConstant< IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsLower< DMatEvalExpr > + : public BoolConstant< IsLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUniLower< DMatEvalExpr > + : public BoolConstant< IsUniLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsStrictlyLower< DMatEvalExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUpper< DMatEvalExpr > + : public BoolConstant< IsUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUniUpper< DMatEvalExpr > + : public BoolConstant< IsUniUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatEvalExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct DMatEvalExprTrait< DMatEvalExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix > + , DMatEvalExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TDMatEvalExprTrait< DMatEvalExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix > + , DMatEvalExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool AF > +struct SubmatrixExprTrait< DMatEvalExpr, AF > +{ + public: + //********************************************************************************************** + using Type = EvalExprTrait_< SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct RowExprTrait< DMatEvalExpr > +{ + public: + //********************************************************************************************** + using Type = EvalExprTrait_< RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct ColumnExprTrait< DMatEvalExpr > +{ + public: + //********************************************************************************************** + using Type = EvalExprTrait_< ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatForEachExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the dense matrix expression. + typedef OppositeType_ OT; //!< Opposite type of the dense matrix expression. + typedef ElementType_ ET; //!< Element type of the dense matrix expression. + typedef ReturnType_ 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::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() }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DMatForEachExpr This; //!< Type of this DMatForEachExpr instance. + typedef ForEachTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + + //! Return type for expression template evaluations. + typedef decltype( std::declval()( std::declval() ) ) 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, 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_ 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, UseSIMDEnabledFlag, HasLoad >::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::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::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 + , IsSame< UnderlyingNumeric, UnderlyingNumeric > > > + assign( DenseMatrix& 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 + , Not< IsSame< UnderlyingNumeric, UnderlyingNumeric > > > > + assign( DenseMatrix& 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_ ); + + 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 > + assign( SparseMatrix& 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_ ); + + 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 > + addAssign( DenseMatrix& 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_ ); + + 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 > + subAssign( DenseMatrix& 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_ ); + + 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 + , IsSame< UnderlyingNumeric, UnderlyingNumeric > > > + smpAssign( DenseMatrix& 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 + , Not< IsSame< UnderlyingNumeric, UnderlyingNumeric > > > > + smpAssign( DenseMatrix& 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_ ); + + 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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_ ); + + 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 > + smpSubAssign( DenseMatrix& 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_ ); + + 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 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 forEach( const DenseMatrix& dm, OP op ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = abs( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr abs( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = floor( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr floor( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = ceil( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr ceil( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 > A, B; + // ... Resizing and initialization + B = conj( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr conj( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 > 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_ ctrans( const DenseMatrix& 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 A, B; + // ... Resizing and initialization + B = real( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr real( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = imag( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr imag( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 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 sqrt( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 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 invsqrt( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 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 cbrt( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 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 invcbrt( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 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,SO> pow( const DenseMatrix& dm, ET exp ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ET ); + + return DMatForEachExpr,SO>( ~dm, Pow( 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 A, B; + // ... Resizing and initialization + B = exp( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr exp( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 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 log( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 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 log10( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = sin( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr sin( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 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 asin( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = sinh( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr sinh( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = asinh( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr asinh( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = cos( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr cos( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 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 acos( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = cosh( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr cosh( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 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 acosh( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = tan( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr tan( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = atan( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr atan( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 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 tanh( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 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 atanh( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = erf( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr erf( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = erfc( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatForEachExpr erfc( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatForEachExpr( ~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& abs( const DMatForEachExpr& 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& floor( const DMatForEachExpr& 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& ceil( const DMatForEachExpr& 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 > 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::Operand conj( const DMatForEachExpr& 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 > 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 conj( const DMatTransExpr,!SO>& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatTransExpr( 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& real( const DMatForEachExpr& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return dm; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO > +struct Rows< DMatForEachExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO > +struct Columns< DMatForEachExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO > +struct IsAligned< DMatForEachExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO > +struct IsPadded< DMatForEachExpr > + : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, typename ET, bool SO > +struct IsSymmetric< DMatForEachExpr,SO> > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< DMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsBuiltin< ElementType_ >::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, typename ET, bool SO > +struct IsHermitian< DMatForEachExpr,SO> > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< DMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; + +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; + +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; + +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; + +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; + +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; + +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; + +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; + +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; + +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; + +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; + +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; + +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; + +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; + +template< typename MT, bool SO > +struct IsLower< DMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ET, bool SO > +struct IsUniLower< DMatForEachExpr,SO> > + : public BoolConstant< IsUniLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyLower< DMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; + +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; + +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; + +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; + +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; + +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; + +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; + +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; + +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; + +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; + +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; + +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; + +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; + +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; + +template< typename MT, bool SO > +struct IsUpper< DMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ET, bool SO > +struct IsUniUpper< DMatForEachExpr,SO> > + : public BoolConstant< IsUniUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; + +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct DMatForEachExprTrait< DMatForEachExpr, Abs > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix > + , DMatForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TDMatForEachExprTrait< DMatForEachExpr, Abs > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix > + , DMatForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct DMatForEachExprTrait< DMatForEachExpr, Floor > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix > + , DMatForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TDMatForEachExprTrait< DMatForEachExpr, Floor > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix > + , DMatForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct DMatForEachExprTrait< DMatForEachExpr, Ceil > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix > + , DMatForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TDMatForEachExprTrait< DMatForEachExpr, Ceil > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix > + , DMatForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct DMatForEachExprTrait< DMatForEachExpr, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix > + , Operand_< DMatForEachExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TDMatForEachExprTrait< DMatForEachExpr, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix > + , Operand_< DMatForEachExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct DMatForEachExprTrait< DMatTransExpr< DMatForEachExpr, false >, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix > + , DMatTransExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TDMatForEachExprTrait< DMatTransExpr< DMatForEachExpr, true >, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix > + , DMatTransExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct DMatForEachExprTrait< DMatForEachExpr, Real > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix > + , DMatForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TDMatForEachExprTrait< DMatForEachExpr, Real > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix > + , DMatForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO, bool AF > +struct SubmatrixExprTrait< DMatForEachExpr, AF > +{ + public: + //********************************************************************************************** + using Type = ForEachExprTrait_< SubmatrixExprTrait_, OP >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO > +struct RowExprTrait< DMatForEachExpr > +{ + public: + //********************************************************************************************** + using Type = ForEachExprTrait_< RowExprTrait_, OP >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO > +struct ColumnExprTrait< DMatForEachExpr > +{ + public: + //********************************************************************************************** + using Type = ForEachExprTrait_< ColumnExprTrait_, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatInvExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the dense matrix expression. + typedef CompositeType_ CT; //!< Composite type of the dense matrix expression. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DMatInvExpr This; //!< Type of this DMatInvExpr instance. + typedef ResultType_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ 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, 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& 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& 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_ ); + + 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& 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& 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 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 or \c complex 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 inv( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + if( !isSquare( ~dm ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" ); + } + + return DMatInvExpr( ~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 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::Operand inv( const DMatInvExpr& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return dm.operand(); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct Rows< DMatInvExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct Columns< DMatInvExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsSymmetric< DMatInvExpr > + : public BoolConstant< IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsHermitian< DMatInvExpr > + : public BoolConstant< IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsLower< DMatInvExpr > + : public BoolConstant< IsUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUniLower< DMatInvExpr > + : public BoolConstant< IsUniUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUpper< DMatInvExpr > + : public BoolConstant< IsLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUniUpper< DMatInvExpr > + : public BoolConstant< IsUniLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct DMatInvExprTrait< DMatInvExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix > + , Operand_< DMatInvExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TDMatInvExprTrait< DMatInvExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix > + , Operand_< DMatInvExpr > + , 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatMatAddExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense matrix expression. + typedef ReturnType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef AddExprTrait_ 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 This; //!< Type of this DMatSMatAddExpr instance. + typedef AddTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::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& 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::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& 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_ ); + + 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& 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& 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 > + smpAssign( DenseMatrix& 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::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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A, C; + blaze::CompressedMatrix 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 + operator+( const DenseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatSMatAddExpr( ~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 A; + blaze::DynamicMatrix 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 + operator+( const SparseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatSMatAddExpr( ~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, T3 > + operator+( const DMatSMatAddExpr& lhs, const DenseMatrix& 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, T3 > + operator-( const DMatSMatAddExpr& lhs, const DenseMatrix& 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 > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct Columns< DMatSMatAddExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsSymmetric< DMatSMatAddExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsHermitian< DMatSMatAddExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsLower< DMatSMatAddExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUniLower< DMatSMatAddExpr > + : public BoolConstant< Or< And< IsUniLower, IsStrictlyLower > + , And< IsUniLower, IsStrictlyLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsStrictlyLower< DMatSMatAddExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUpper< DMatSMatAddExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUniUpper< DMatSMatAddExpr > + : public BoolConstant< Or< And< IsUniUpper, IsStrictlyUpper > + , And< IsUniUpper, IsStrictlyUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsStrictlyUpper< DMatSMatAddExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatAddExprTrait< DMatSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatSMatAddExprTrait_< DMatDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatAddExprTrait< DMatSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix , IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix , IsColumnMajorMatrix > + , DMatSMatAddExprTrait_< DMatTDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct TDMatDMatAddExprTrait< DMatSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix , IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix , IsRowMajorMatrix > + , DMatTSMatAddExprTrait_< TDMatDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct TDMatTDMatAddExprTrait< DMatSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix , IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix , IsColumnMajorMatrix > + , TDMatTSMatAddExprTrait_< TDMatTDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatSubExprTrait< DMatSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatSMatAddExprTrait_< DMatDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatSubExprTrait< DMatSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , DMatSMatAddExprTrait_< DMatTDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct TDMatDMatSubExprTrait< DMatSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatTSMatAddExprTrait_< TDMatDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct TDMatTDMatSubExprTrait< DMatSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDMatTSMatAddExprTrait_< TDMatTDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO, bool AF > +struct SubmatrixExprTrait< DMatSMatAddExpr, AF > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct RowExprTrait< DMatSMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct ColumnExprTrait< DMatSMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side sparse matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::value || IsSymmetric::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::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::value && + !IsResizable< ElementType_ >::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::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DMatSMatMultExpr This; //!< Type of this DMatSMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 > + assign( DenseMatrix& 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_ ConstIterator; + + reset( C ); + + for( size_t j=0UL; j::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iiend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( A.rows() ) ); + BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" ); + + for( size_t ii=iibegin; ii iiend )?( iiend ):( ii+8UL ) ); + + for( ; element!=end; ++element ) { + for( size_t i=ii; iindex()) ) ) + 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 > + 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 > + selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + reset( C ); + + for( size_t j=0UL; j::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iiend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( A.rows() ) ); + BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" ); + + for( size_t ii=iibegin; ii iiend )?( iiend ):( ii+8UL ) ); + + for( ; element!=end; ++element ) { + for( size_t i=ii; iindex()) += 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 > + 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 > + selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_ ); + + const OppositeType_ 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 > + assign( SparseMatrix& 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_ ); + + 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 > + assign( Matrix& 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::value && IsSymmetric::value ) + assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + addAssign( DenseMatrix& 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_ ConstIterator; + + for( size_t j=0UL; j::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iiend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( A.rows() ) ); + BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" ); + + for( size_t ii=iibegin; ii iiend )?( iiend ):( ii+8UL ) ); + + for( ; element!=end; ++element ) { + for( size_t i=ii; iindex()) += 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_ ); + + const OppositeType_ 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 > + addAssign( Matrix& 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::value && IsSymmetric::value ) + addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + subAssign( DenseMatrix& 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_ ConstIterator; + + for( size_t j=0UL; j::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iiend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( A.rows() ) ); + BLAZE_INTERNAL_ASSERT( iibegin <= iiend, "Invalid loop indices detected" ); + + for( size_t ii=iibegin; ii iiend )?( iiend ):( ii+8UL ) ); + + for( ; element!=end; ++element ) { + for( size_t i=ii; iindex()) -= 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_ ); + + const OppositeType_ 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 > + subAssign( Matrix& 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::value && IsSymmetric::value ) + subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAssign( Matrix& 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::value && IsSymmetric::value ) + smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + smpAddAssign( DenseMatrix& 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 > + smpAddAssign( Matrix& 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::value && IsSymmetric::value ) + smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + smpSubAssign( DenseMatrix& 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 > + smpSubAssign( Matrix& 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::value && IsSymmetric::value ) + smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 A, C; + blaze::CompressedMatrix 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 + operator*( const DenseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatSMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< DMatSMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< DMatSMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsAligned< DMatSMatMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< DMatSMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< DMatSMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< DMatSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< DMatSMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< DMatSMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< DMatSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct DMatDVecMultExprTrait< DMatSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseVector, IsColumnVector > + , DMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct DMatSVecMultExprTrait< DMatSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsSparseVector, IsColumnVector > + , DMatSVecMultExprTrait_< MT1, SMatSVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecDMatMultExprTrait< VT, DMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , TDVecSMatMultExprTrait_< TDVecDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecDMatMultExprTrait< VT, DMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , TDVecSMatMultExprTrait_< TDVecDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< DMatSMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< DMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< DMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatMatSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense matrix expression. + typedef ReturnType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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 This; //!< Type of this DMatSMatSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::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& 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::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& 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_ ); + + 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& 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& 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 > + smpAssign( DenseMatrix& 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::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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A, C; + blaze::CompressedMatrix 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 + operator-( const DenseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatSMatSubExpr( ~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, T3 > + operator+( const DMatSMatSubExpr& lhs, const DenseMatrix& 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, T3 > + operator-( const DMatSMatSubExpr& lhs, const DenseMatrix& 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 > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct Columns< DMatSMatSubExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsSymmetric< DMatSMatSubExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsHermitian< DMatSMatSubExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsLower< DMatSMatSubExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUniLower< DMatSMatSubExpr > + : public BoolConstant< And< IsUniLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsStrictlyLower< DMatSMatSubExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUpper< DMatSMatSubExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUniUpper< DMatSMatSubExpr > + : public BoolConstant< And< IsUniUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsStrictlyUpper< DMatSMatSubExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatAddExprTrait< DMatSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatSMatSubExprTrait_< DMatDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatAddExprTrait< DMatSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , DMatSMatSubExprTrait_< DMatTDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct TDMatDMatAddExprTrait< DMatSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatTSMatSubExprTrait_< TDMatDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct TDMatTDMatAddExprTrait< DMatSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDMatTSMatSubExprTrait_< TDMatTDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatSubExprTrait< DMatSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatSMatSubExprTrait_< DMatDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatSubExprTrait< DMatSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , DMatSMatSubExprTrait_< DMatTDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct TDMatDMatSubExprTrait< DMatSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatTSMatSubExprTrait_< TDMatDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct TDMatTDMatSubExprTrait< DMatSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDMatTSMatSubExprTrait_< TDMatTDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO, bool AF > +struct SubmatrixExprTrait< DMatSMatSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct RowExprTrait< DMatSMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct ColumnExprTrait< DMatSMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ MRT; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ VRT; //!< Result type of the right-hand side sparse vector expression. + typedef CompositeType_ MCT; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side sparse vector expression. + enum : bool { evaluateVector = IsComputation::value || RequiresEvaluation::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 This; //!< Type of this DMatSVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT, const MT& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, 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::value ) + { + return mat_(index,index) * vec_[index]; + } + else if( IsLower::value ) + { + const size_t n( IsStrictlyLower::value ? index : index+1UL ); + return subvector( row( mat_, index ), 0UL, n ) * subvector( vec_, 0UL, n ); + } + else if( IsUpper::value ) + { + const size_t begin( IsStrictlyUpper::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 > + assign( DenseVector& 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 > + assign( SparseVector& 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_ ); + + 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 > + addAssign( DenseVector& 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 > + subAssign( DenseVector& 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 > + multAssign( DenseVector& 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_ ); + + 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 > + divAssign( DenseVector& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 A; + blaze::CompressedVector x; + blaze::DynamicVector 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, IsMatMatMultExpr > + , DMatSVecMultExpr > + operator*( const DenseMatrix& mat, const SparseVector& vec ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~mat).columns() != (~vec).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" ); + } + + return DMatSVecMultExpr( ~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, MultExprTrait_ > + operator*( const DenseMatrix& mat, const SparseVector& 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, MultExprTrait_ > + operator*( const DenseMatrix& mat, const SparseVector& 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 > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT > +struct IsAligned< DMatSVecMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, bool AF > +struct SubvectorExprTrait< DMatSVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatScalarDivExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the dense matrix expression. + typedef ReturnType_ RN; //!< Return type of the dense matrix expression. + typedef ElementType_ ET; //!< Element type of the dense matrix expression. + typedef CompositeType_ 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::value }; + + //! Expression return type for the subscript operator. + typedef DivExprTrait_ 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::value && RequiresEvaluation::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 This; //!< Type of this DMatScalarDivExpr instance. + typedef DivTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, 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_ 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::value && + ( HasSIMDDiv::value || + HasSIMDDiv,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::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::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 > + assign( DenseMatrix& 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 > + assign( SparseMatrix& 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 > + addAssign( DenseMatrix& 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_ ); + + 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 > + subAssign( DenseMatrix& 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_ ); + + 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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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 > + smpAddAssign( DenseMatrix& 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_ ); + + 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 > + smpSubAssign( DenseMatrix& 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_ ); + + 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 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, DivExprTrait_ > + operator/( const DenseMatrix& mat, T2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_USER_ASSERT( scalar != T2(0), "Division by zero detected" ); + + typedef DivExprTrait_ ReturnType; + typedef RightOperand_ ScalarType; + + if( IsMultExpr::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, Or< IsInvertible, IsInvertible > > + , MultExprTrait_< DMatScalarDivExpr, ST2 > > + operator*( const DMatScalarDivExpr& 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, Or< IsInvertible, IsInvertible > > + , MultExprTrait_< ST1, DMatScalarDivExpr > > + operator*( ST1 scalar, const DMatScalarDivExpr& 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 + , DivExprTrait_< MT, MultTrait_ > > + operator/( const DMatScalarDivExpr& mat, ST2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_USER_ASSERT( scalar != ST2(0), "Division by zero detected" ); + + typedef MultTrait_ MultType; + typedef DivExprTrait_ ReturnType; + typedef RightOperand_ ScalarType; + + if( IsMultExpr::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 > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct Columns< DMatScalarDivExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsAligned< DMatScalarDivExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsPadded< DMatScalarDivExpr > + : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsSymmetric< DMatScalarDivExpr > + : public BoolConstant< IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsHermitian< DMatScalarDivExpr > + : public BoolConstant< IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsLower< DMatScalarDivExpr > + : public BoolConstant< IsLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsStrictlyLower< DMatScalarDivExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsUpper< DMatScalarDivExpr > + : public BoolConstant< IsUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsStrictlyUpper< DMatScalarDivExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DMATSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename ST2 > +struct DMatScalarMultExprTrait< DMatScalarDivExpr, ST2 > +{ + private: + //********************************************************************************************** + typedef DivTrait_ ScalarType; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix, IsNumeric, IsNumeric > + , If_< IsInvertible + , DMatScalarMultExprTrait_ + , DMatScalarMultExpr< DMatScalarDivExpr, ST2, false > > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDMATSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename ST2 > +struct TDMatScalarMultExprTrait< DMatScalarDivExpr, ST2 > +{ + private: + //********************************************************************************************** + typedef DivTrait_ ScalarType; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix, IsNumeric, IsNumeric > + , If_< IsInvertible + , DMatScalarMultExprTrait_ + , DMatScalarMultExpr< DMatScalarDivExpr, ST2, true > > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO, bool AF > +struct SubmatrixExprTrait< DMatScalarDivExpr, AF > +{ + public: + //********************************************************************************************** + using Type = DivExprTrait_< SubmatrixExprTrait_, ST >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct RowExprTrait< DMatScalarDivExpr > +{ + public: + //********************************************************************************************** + using Type = DivExprTrait_< RowExprTrait_, ST >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct ColumnExprTrait< DMatScalarDivExpr > +{ + public: + //********************************************************************************************** + using Type = DivExprTrait_< ColumnExprTrait_, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatScalarMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the dense matrix expression. + typedef ReturnType_ RN; //!< Return type of the dense matrix expression. + typedef ElementType_ ET; //!< Element type of the dense matrix expression. + typedef CompositeType_ 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::value }; + + //! Expression return type for the subscript operator. + typedef MultExprTrait_ 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::value && RequiresEvaluation::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 This; //!< Type of this DMatScalarMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, 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_ 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::value && + ( HasSIMDMult::value || + HasSIMDMult,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::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::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 > + assign( DenseMatrix& 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 > + assign( SparseMatrix& 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 > + addAssign( DenseMatrix& 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_ ); + + 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 > + subAssign( DenseMatrix& 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_ ); + + 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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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 > + smpAddAssign( DenseMatrix& 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_ ); + + 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 > + smpSubAssign( DenseMatrix& 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_ ); + + 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 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,SO> + operator-( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + typedef UnderlyingBuiltin_ ElementType; + return DMatScalarMultExpr( ~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 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, MultExprTrait_ > + operator*( const DenseMatrix& mat, T2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + return MultExprTrait_( ~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 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, MultExprTrait_ > + operator*( T1 scalar, const DenseMatrix& mat ) +{ + BLAZE_FUNCTION_TRACE; + + return MultExprTrait_( ~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 + operator-( const DMatScalarMultExpr& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatScalarMultExpr( 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, MultExprTrait_< DMatScalarMultExpr, ST2 > > + operator*( const DMatScalarMultExpr& 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, MultExprTrait_< ST1, DMatScalarMultExpr > > + operator*( ST1 scalar, const DMatScalarMultExpr& 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, Or< IsInvertible, IsInvertible > > + , DivExprTrait_< DMatScalarMultExpr, ST2 > > + operator/( const DMatScalarMultExpr& 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, VT > + operator*( const DMatScalarMultExpr& mat, const DenseVector& 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 > + operator*( const DenseVector& vec, const DMatScalarMultExpr& 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_, MultTrait_, false > + operator*( const DMatScalarMultExpr& mat, const DVecScalarMultExpr& 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, DMatScalarMultExpr > + operator*( const DVecScalarMultExpr& vec, const DMatScalarMultExpr& 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, VT > + operator*( const DMatScalarMultExpr& mat, const SparseVector& 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 > + operator*( const SparseVector& vec, const DMatScalarMultExpr& 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, SVecScalarMultExpr > + operator*( const DMatScalarMultExpr& mat, const SVecScalarMultExpr& 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, DMatScalarMultExpr > + operator*( const SVecScalarMultExpr& vec, const DMatScalarMultExpr& 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, MT2 > + operator*( const DMatScalarMultExpr& lhs, const DenseMatrix& 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 > + operator*( const DenseMatrix& lhs, const DMatScalarMultExpr& 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, DMatScalarMultExpr > + operator*( const DMatScalarMultExpr& lhs, const DMatScalarMultExpr& 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, MT2 > + operator*( const DMatScalarMultExpr& lhs, const SparseMatrix& 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 > + operator*( const SparseMatrix& lhs, const DMatScalarMultExpr& 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, SMatScalarMultExpr > + operator*( const DMatScalarMultExpr& mat, const SMatScalarMultExpr& 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, DMatScalarMultExpr > + operator*( const SMatScalarMultExpr& mat, const DMatScalarMultExpr& 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 > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct Columns< DMatScalarMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsAligned< DMatScalarMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsPadded< DMatScalarMultExpr > + : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsSymmetric< DMatScalarMultExpr > + : public BoolConstant< IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsHermitian< DMatScalarMultExpr > + : public BoolConstant< IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsLower< DMatScalarMultExpr > + : public BoolConstant< IsLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsStrictlyLower< DMatScalarMultExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsUpper< DMatScalarMultExpr > + : public BoolConstant< IsUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsStrictlyUpper< DMatScalarMultExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DMATSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename ST2 > +struct DMatScalarMultExprTrait< DMatScalarMultExpr, ST2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix, IsNumeric, IsNumeric > + , DMatScalarMultExprTrait_< MT, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDMATSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename ST2 > +struct TDMatScalarMultExprTrait< DMatScalarMultExpr, ST2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix, IsNumeric, IsNumeric > + , TDMatScalarMultExprTrait_< MT, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DMATSCALARDIVEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename ST2 > +struct DMatScalarDivExprTrait< DMatScalarMultExpr, ST2 > +{ + private: + //********************************************************************************************** + typedef DivTrait_ ScalarType; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix, IsNumeric, IsNumeric > + , If_< IsInvertible + , DMatScalarMultExprTrait_ + , DMatScalarDivExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDMATSCALARDIVEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename ST2 > +struct TDMatScalarDivExprTrait< DMatScalarMultExpr, ST2 > +{ + private: + //********************************************************************************************** + typedef DivTrait_ ScalarType; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix, IsNumeric, IsNumeric > + , If_< IsInvertible + , TDMatScalarMultExprTrait_ + , TDMatScalarDivExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DMATDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, typename VT > +struct DMatDVecMultExprTrait< DMatScalarMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsDenseVector, IsColumnVector + , IsNumeric > + , DVecScalarMultExprTrait_< DMatDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename VT, typename ST2 > +struct DMatDVecMultExprTrait< DMatScalarMultExpr, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsDenseVector, IsColumnVector + , IsNumeric, IsNumeric > + , DVecScalarMultExprTrait_< DMatDVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDMATDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, typename VT > +struct TDMatDVecMultExprTrait< DMatScalarMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector + , IsNumeric > + , DVecScalarMultExprTrait_< TDMatDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename VT, typename ST2 > +struct TDMatDVecMultExprTrait< DMatScalarMultExpr, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector + , IsNumeric, IsNumeric > + , DVecScalarMultExprTrait_< TDMatDVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDVECDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, typename ST > +struct TDVecDMatMultExprTrait< VT, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric > + , TDVecScalarMultExprTrait_< TDVecDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename MT, typename ST2 > +struct TDVecDMatMultExprTrait< DVecScalarMultExpr, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , TDVecScalarMultExprTrait_< TDVecDMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDVECTDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, typename ST > +struct TDVecTDMatMultExprTrait< VT, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TDVecScalarMultExprTrait_< TDVecTDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename MT, typename ST2 > +struct TDVecTDMatMultExprTrait< DVecScalarMultExpr, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , TDVecScalarMultExprTrait_< TDVecTDMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DMATSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, typename VT > +struct DMatSVecMultExprTrait< DMatScalarMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseVector, IsColumnVector + , IsNumeric > + , DVecScalarMultExprTrait_< DMatSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename VT, typename ST2 > +struct DMatSVecMultExprTrait< DMatScalarMultExpr, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseVector, IsColumnVector + , IsNumeric, IsNumeric > + , DVecScalarMultExprTrait_< DMatSVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDMATSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, typename VT > +struct TDMatSVecMultExprTrait< DMatScalarMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector + , IsNumeric > + , DVecScalarMultExprTrait_< TDMatSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename VT, typename ST2 > +struct TDMatSVecMultExprTrait< DMatScalarMultExpr, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector + , IsNumeric, IsNumeric > + , DVecScalarMultExprTrait_< TDMatSVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSVECDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, typename ST > +struct TSVecDMatMultExprTrait< VT, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric > + , TDVecScalarMultExprTrait_< TSVecDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename MT, typename ST2 > +struct TSVecDMatMultExprTrait< SVecScalarMultExpr, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , TDVecScalarMultExprTrait_< TSVecDMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSVECTDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, typename ST > +struct TSVecTDMatMultExprTrait< VT, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TDVecScalarMultExprTrait_< TSVecTDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename MT, typename ST2 > +struct TSVecTDMatMultExprTrait< SVecScalarMultExpr, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , TDVecScalarMultExprTrait_< TSVecTDMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DMATDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct DMatDMatMultExprTrait< DMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric > + , DMatScalarMultExprTrait_< DMatDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename ST > +struct DMatDMatMultExprTrait< MT1, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric > + , DMatScalarMultExprTrait_< DMatDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct DMatDMatMultExprTrait< DMatScalarMultExpr, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , DMatScalarMultExprTrait_< DMatDMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DMATTDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct DMatTDMatMultExprTrait< DMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric > + , DMatScalarMultExprTrait_< DMatTDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename ST > +struct DMatTDMatMultExprTrait< MT1, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric > + , DMatScalarMultExprTrait_< DMatTDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct DMatTDMatMultExprTrait< DMatScalarMultExpr, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , DMatScalarMultExprTrait_< DMatTDMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDMATDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct TDMatDMatMultExprTrait< DMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric > + , TDMatScalarMultExprTrait_< TDMatDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename ST > +struct TDMatDMatMultExprTrait< MT1, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric > + , TDMatScalarMultExprTrait_< TDMatDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct TDMatDMatMultExprTrait< DMatScalarMultExpr, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , TDMatScalarMultExprTrait_< TDMatDMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDMATTDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct TDMatTDMatMultExprTrait< DMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TDMatScalarMultExprTrait_< TDMatTDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename ST > +struct TDMatTDMatMultExprTrait< MT1, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TDMatScalarMultExprTrait_< TDMatTDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct TDMatTDMatMultExprTrait< DMatScalarMultExpr, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , TDMatScalarMultExprTrait_< TDMatTDMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DMATSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct DMatSMatMultExprTrait< DMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric > + , DMatScalarMultExprTrait_< DMatSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct DMatSMatMultExprTrait< DMatScalarMultExpr, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , DMatScalarMultExprTrait_< DMatSMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DMATTSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct DMatTSMatMultExprTrait< DMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric > + , DMatScalarMultExprTrait_< DMatTSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct DMatTSMatMultExprTrait< DMatScalarMultExpr, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , DMatScalarMultExprTrait_< DMatTSMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDMATSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct TDMatSMatMultExprTrait< DMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric > + , TDMatScalarMultExprTrait_< TDMatSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct TDMatSMatMultExprTrait< DMatScalarMultExpr, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , TDMatScalarMultExprTrait_< TDMatSMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDMATTSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct TDMatTSMatMultExprTrait< DMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TDMatScalarMultExprTrait_< TDMatTSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct TDMatTSMatMultExprTrait< DMatScalarMultExpr, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , TDMatScalarMultExprTrait_< TDMatTSMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SMATDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct SMatDMatMultExprTrait< MT1, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric > + , DMatScalarMultExprTrait_< SMatDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct SMatDMatMultExprTrait< SMatScalarMultExpr, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , DMatScalarMultExprTrait_< SMatDMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SMATTDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct SMatTDMatMultExprTrait< MT1, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric > + , DMatScalarMultExprTrait_< SMatTDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct SMatTDMatMultExprTrait< SMatScalarMultExpr, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , DMatScalarMultExprTrait_< SMatTDMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSMATDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct TSMatDMatMultExprTrait< MT1, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric > + , TDMatScalarMultExprTrait_< TSMatDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct TSMatDMatMultExprTrait< SMatScalarMultExpr, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , TDMatScalarMultExprTrait_< TSMatDMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSMATTDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct TSMatTDMatMultExprTrait< MT1, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TDMatScalarMultExprTrait_< TSMatTDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct TSMatTDMatMultExprTrait< SMatScalarMultExpr, DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , TDMatScalarMultExprTrait_< TSMatTDMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO, bool AF > +struct SubmatrixExprTrait< DMatScalarMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_, ST >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct RowExprTrait< DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, ST >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct ColumnExprTrait< DMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< ColumnExprTrait_, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatSerialExpr + , private Computation +{ + public: + //**Type definitions**************************************************************************** + typedef DMatSerialExpr This; //!< Type of this DMatSerialExpr instance. + typedef ResultType_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ 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, 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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 A, B; + // ... Resizing and initialization + B = serial( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatSerialExpr serial( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatSerialExpr( ~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 serial( const DMatSerialExpr& dm ) +{ + return dm; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct Rows< DMatSerialExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct Columns< DMatSerialExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsAligned< DMatSerialExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsSymmetric< DMatSerialExpr > + : public BoolConstant< IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsHermitian< DMatSerialExpr > + : public BoolConstant< IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsLower< DMatSerialExpr > + : public BoolConstant< IsLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUniLower< DMatSerialExpr > + : public BoolConstant< IsUniLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsStrictlyLower< DMatSerialExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUpper< DMatSerialExpr > + : public BoolConstant< IsUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUniUpper< DMatSerialExpr > + : public BoolConstant< IsUniUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatSerialExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct DMatSerialExprTrait< DMatSerialExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix > + , DMatSerialExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TDMatSerialExprTrait< DMatSerialExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix > + , DMatSerialExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool AF > +struct SubmatrixExprTrait< DMatSerialExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SerialExprTrait_< SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct RowExprTrait< DMatSerialExpr > +{ + public: + //********************************************************************************************** + using Type = SerialExprTrait_< RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct ColumnExprTrait< DMatSerialExpr > +{ + public: + //********************************************************************************************** + using Type = SerialExprTrait_< ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatAddExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense matrix expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef AddExprTrait_ 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::value || RequiresEvaluation::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 This; //!< Type of this DMatTDMatAdd instance. + typedef AddTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side dense matrix expression. + typedef If_< IsExpression, 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::value && ( RequiresEvaluation::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) || + ( IsExpression::value && ( RequiresEvaluation::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 > + assign( DenseMatrix& 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 // Storage order of the target dense matrix + friend inline EnableIf_< UseAssign > + assign( DenseMatrix& 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::value && isSame( ~lhs, rhs.lhs_ ) ) { + addAssign( ~lhs, rhs.rhs_ ); + } + else if( !IsExpression::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& 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_ ); + + 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 > + addAssign( DenseMatrix& 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 // Storage order of the target dense matrix + friend inline EnableIf_< UseAssign > + addAssign( DenseMatrix& 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 > + subAssign( DenseMatrix& 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 // Storage order of the target dense matrix + friend inline EnableIf_< UseAssign > + subAssign( DenseMatrix& 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 > + smpAssign( DenseMatrix& 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::value && isSame( ~lhs, rhs.lhs_ ) ) { + smpAddAssign( ~lhs, rhs.rhs_ ); + } + else if( !IsExpression::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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A, C; + blaze::DynamicMatrix 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 >, Not< IsSymmetric > > + , const DMatTDMatAddExpr > + operator+( const DenseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatTDMatAddExpr( ~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 A; + blaze::DynamicMatrix 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 >, Not< IsSymmetric > > + , const DMatTDMatAddExpr > + operator+( const DenseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatTDMatAddExpr( ~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, Not< IsSymmetric > >, const AddExprTrait_ > + operator+( const DenseMatrix& lhs, const DenseMatrix& 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, const AddExprTrait_ > + operator+( const DenseMatrix& lhs, const DenseMatrix& 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 >, IsSymmetric >, const AddExprTrait_ > + operator+( const DenseMatrix& lhs, const DenseMatrix& 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, const AddExprTrait_ > + operator+( const DenseMatrix& lhs, const DenseMatrix& 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 > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< DMatTDMatAddExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsAligned< DMatTDMatAddExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< DMatTDMatAddExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< DMatTDMatAddExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< DMatTDMatAddExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< DMatTDMatAddExpr > + : public BoolConstant< Or< And< IsUniLower, IsStrictlyLower > + , And< IsUniLower, IsStrictlyLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< DMatTDMatAddExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< DMatTDMatAddExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< DMatTDMatAddExpr > + : public BoolConstant< Or< And< IsUniUpper, IsStrictlyUpper > + , And< IsUniUpper, IsStrictlyUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< DMatTDMatAddExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< DMatTDMatAddExpr, AF > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< DMatTDMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< DMatTDMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side dense matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::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::value && !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DMatTDMatMultExpr This; //!< Type of this DMatTDMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side dense matrix expression. + typedef If_< IsExpression, 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::value && !IsDiagonal::value && + MT1::simdEnabled && MT2::simdEnabled && + HasSIMDAdd::value && + HasSIMDMult::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::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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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& 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::value || IsDiagonal::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 >, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( ( IsStrictlyLower::value && M > 1UL ) ? 2UL : 1UL ) + :( 0UL ) ); + const size_t iend( ( IsStrictlyUpper::value ) + ?( ( IsStrictlyUpper::value && M > 1UL ) ? M-2UL : M-1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=0UL; i::value && IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( IsStrictlyUpper::value ? i+2UL : i+1UL ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsStrictlyUpper::value ? 1UL : 0UL ) ); + const size_t jend( ( IsLower::value && IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( IsStrictlyLower::value ? i-1UL : i ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsStrictlyLower::value ? N-1UL : N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=0UL; j::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( ( IsStrictlyUpper::value && N > 1UL ) ? 2UL : 1UL ) + :( 0UL ) ); + const size_t jend( ( IsStrictlyLower::value ) + ?( ( IsStrictlyLower::value && N > 1UL ) ? N-2UL : N-1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=0UL; j::value && IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( IsStrictlyLower::value ? j+2UL : j+1UL ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsStrictlyLower::value ? 1UL : 0UL ) ); + const size_t iend( ( IsUpper::value && IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( ( IsStrictlyUpper::value )?( j-1UL ):( j ) ) + :( ( IsStrictlyUpper::value )?( j ):( j+1UL ) ) ) + :( IsStrictlyUpper::value ? M-1UL : M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=0UL; i::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + if( IsUpper::value ) { + for( size_t j=0UL; j::value ) { + for( size_t j=jend; j // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t ipos( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::value ? j : j+1UL ), iend ) ) + :( iend ) ); + + if( IsLower::value ) { + for( size_t i=ii; i::value ) { + for( size_t i=ipos; i // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jpos( ( IsLower::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), jend ) ) + :( jend ) ); + + if( IsUpper::value ) { + for( size_t j=jj; j::value ) { + for( size_t j=jpos; j // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + if( IsLower::value ) { + for( size_t i=0UL; i::value ) { + for( size_t i=iend; i // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + reset( C ); + + for( size_t i=0UL; i // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+4UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+2UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+4UL, j+2UL ) : ( i+4UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+2UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeAssignKernel( DenseMatrix& 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 > + selectLargeAssignKernel( DenseMatrix& 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 > + 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 > + selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( C, B ); + trmm( C, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(1) ); + } + else if( IsTriangular::value ) { + assign( C, A ); + trmm( C, B, CblasRight, ( IsLower::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& 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_ ); + + 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& 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::value || IsDiagonal::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 >, Not< IsDiagonal > > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( ( IsStrictlyLower::value && M > 1UL ) ? 2UL : 1UL ) + :( 0UL ) ); + const size_t iend( ( IsStrictlyUpper::value ) + ?( ( IsStrictlyUpper::value && M > 1UL ) ? M-2UL : M-1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i::value && IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( IsStrictlyUpper::value ? i+2UL : i+1UL ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsStrictlyUpper::value ? 1UL : 0UL ) ); + const size_t jend( ( IsLower::value && IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( IsStrictlyLower::value ? i-1UL : i ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsStrictlyLower::value ? N-1UL : N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, Not< IsDiagonal > > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( ( IsStrictlyUpper::value && N > 1UL ) ? 2UL : 1UL ) + :( 0UL ) ); + const size_t jend( ( IsStrictlyLower::value ) + ?( ( IsStrictlyLower::value && N > 1UL ) ? N-2UL : N-1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j::value && IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( IsStrictlyLower::value ? j+2UL : j+1UL ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsStrictlyLower::value ? 1UL : 0UL ) ); + const size_t iend( ( IsUpper::value && IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( ( IsStrictlyUpper::value )?( j-1UL ):( j ) ) + :( ( IsStrictlyUpper::value )?( j ):( j+1UL ) ) ) + :( IsStrictlyUpper::value ? M-1UL : M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t ipos( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::value ? j : j+1UL ), iend ) ) + :( iend ) ); + + for( size_t i=ibegin; i // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jpos( ( IsLower::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), jend ) ) + :( jend ) ); + + for( size_t j=jbegin; j // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + for( size_t i=0UL; i // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAddAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+4UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+2UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallAddAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+4UL, j+2UL ) : ( i+4UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+2UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeAddAssignKernel( DenseMatrix& 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 > + selectLargeAddAssignKernel( DenseMatrix& 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 > + 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 > + selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(1) ); + addAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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& 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::value || IsDiagonal::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 >, Not< IsDiagonal > > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( ( IsStrictlyLower::value && M > 1UL ) ? 2UL : 1UL ) + :( 0UL ) ); + const size_t iend( ( IsStrictlyUpper::value ) + ?( ( IsStrictlyUpper::value && M > 1UL ) ? M-2UL : M-1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i::value && IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( IsStrictlyUpper::value ? i+2UL : i+1UL ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsStrictlyUpper::value ? 1UL : 0UL ) ); + const size_t jend( ( IsLower::value && IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( IsStrictlyLower::value ? i-1UL : i ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsStrictlyLower::value ? N-1UL : N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, Not< IsDiagonal > > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( ( IsStrictlyUpper::value && N > 1UL ) ? 2UL : 1UL ) + :( 0UL ) ); + const size_t jend( ( IsStrictlyLower::value ) + ?( ( IsStrictlyLower::value && N > 1UL ) ? N-2UL : N-1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j::value && IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( IsStrictlyLower::value ? j+2UL : j+1UL ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsStrictlyLower::value ? 1UL : 0UL ) ); + const size_t iend( ( IsUpper::value && IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( ( IsStrictlyUpper::value )?( j-1UL ):( j ) ) + :( ( IsStrictlyUpper::value )?( j ):( j+1UL ) ) ) + :( IsStrictlyUpper::value ? M-1UL : M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t ipos( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::value ? j : j+1UL ), iend ) ) + :( iend ) ); + + for( size_t i=ibegin; i // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jpos( ( IsLower::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), jend ) ) + :( jend ) ); + + for( size_t j=jbegin; j // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + for( size_t i=0UL; i // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallSubAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+4UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+2UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallSubAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+4UL, j+2UL ) : ( i+4UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+2UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeSubAssignKernel( DenseMatrix& 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 > + selectLargeSubAssignKernel( DenseMatrix& 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 > + 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 > + selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(1) ); + subAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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, ST, false > + : public DenseMatrix< DMatScalarMultExpr< DMatTDMatMultExpr, ST, false >, false > + , private MatScalarMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef DMatTDMatMultExpr MMM; //!< Type of the dense matrix multiplication expression. + typedef ResultType_ RES; //!< Result type of the dense matrix multiplication expression. + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side dense matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + !( IsBuiltin< ElementType_ >::value && IsComplex::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::value && !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ + , T4 >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DMatScalarMultExpr This; //!< Type of this DMatScalarMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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 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::value && !IsDiagonal::value && + MT1::simdEnabled && MT2::simdEnabled && + AreSIMDCombinable::value && + HasSIMDAdd::value && + HasSIMDMult::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::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_ 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& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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::value || IsDiagonal::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 >, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( ( IsStrictlyLower::value && M > 1UL ) ? 2UL : 1UL ) + :( 0UL ) ); + const size_t iend( ( IsStrictlyUpper::value ) + ?( ( IsStrictlyUpper::value && M > 1UL ) ? M-2UL : M-1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=0UL; i::value && IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( IsStrictlyUpper::value ? i+2UL : i+1UL ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsStrictlyUpper::value ? 1UL : 0UL ) ); + const size_t jend( ( IsLower::value && IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( IsStrictlyLower::value ? i-1UL : i ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsStrictlyLower::value ? N-1UL : N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=0UL; j::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline EnableIf_< And< Not< IsDiagonal >, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( ( IsStrictlyUpper::value && N > 1UL ) ? 2UL : 1UL ) + :( 0UL ) ); + const size_t jend( ( IsStrictlyLower::value ) + ?( ( IsStrictlyLower::value && N > 1UL ) ? N-2UL : N-1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=0UL; j::value && IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( IsStrictlyLower::value ? j+2UL : j+1UL ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsStrictlyLower::value ? 1UL : 0UL ) ); + const size_t iend( ( IsUpper::value && IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( ( IsStrictlyUpper::value )?( j-1UL ):( j ) ) + :( ( IsStrictlyUpper::value )?( j ):( j+1UL ) ) ) + :( IsStrictlyUpper::value ? M-1UL : M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=0UL; i::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + if( IsUpper::value ) { + for( size_t j=0UL; j::value ) { + for( size_t j=jend; j // Type of the scalar value + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t ipos( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::value ? j : j+1UL ), iend ) ) + :( iend ) ); + + if( IsLower::value ) { + for( size_t i=ii; i::value ) { + for( size_t i=ipos; i // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jpos( ( IsLower::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), jend ) ) + :( jend ) ); + + if( IsUpper::value ) { + for( size_t j=jj; j::value ) { + for( size_t j=jpos; j // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + if( IsLower::value ) { + for( size_t i=0UL; i::value ) { + for( size_t i=iend; i // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + reset( C ); + + for( size_t i=0UL; i // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+4UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+2UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::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 // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+4UL, j+2UL ) : ( i+4UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+2UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeAssignKernel( DenseMatrix& 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 > + selectLargeAssignKernel( DenseMatrix& 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 > + 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 > + selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( C, B ); + trmm( C, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(scalar) ); + } + else if( IsTriangular::value ) { + assign( C, A ); + trmm( C, B, CblasRight, ( IsLower::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& 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_ ); + + 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& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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::value || IsDiagonal::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 >, Not< IsDiagonal > > > + 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 >, IsDiagonal > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the scalar value + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t ipos( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::value ? j : j+1UL ), iend ) ) + :( iend ) ); + + for( size_t i=ibegin; i // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jpos( ( IsLower::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), jend ) ) + :( jend ) ); + + for( size_t j=jbegin; j // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + for( size_t i=0UL; i // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAddAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+4UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+2UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::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 // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallAddAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+4UL, j+2UL ) : ( i+4UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+2UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeAddAssignKernel( DenseMatrix& 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 > + selectLargeAddAssignKernel( DenseMatrix& 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 > + 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 > + selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(scalar) ); + addAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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::value || IsDiagonal::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 >, Not< IsDiagonal > > > + 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 >, IsDiagonal > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the scalar value + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t ipos( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::value ? j : j+1UL ), iend ) ) + :( iend ) ); + + for( size_t i=ibegin; i // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jpos( ( IsLower::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), jend ) ) + :( jend ) ); + + for( size_t j=jbegin; j // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + for( size_t i=0UL; i // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallSubAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+4UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+2UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::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 // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallSubAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+4UL, j+2UL ) : ( i+4UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsUpper::value ? min( i+2UL, j+2UL ) : ( i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::value ? ( j & size_t(-SIMDSIZE) ) : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ? max( i, j ) : i ) & size_t(-SIMDSIZE) ) + :( IsLower::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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeSubAssignKernel( DenseMatrix& 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 > + selectLargeSubAssignKernel( DenseMatrix& 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 > + 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 > + selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(scalar) ); + subAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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 > + smpAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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 > + smpSubAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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 A, C; + blaze::DynamicMatrix 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 + operator*( const DenseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatTDMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< DMatTDMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< DMatTDMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsAligned< DMatTDMatMultExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< DMatTDMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< DMatTDMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< DMatTDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< DMatTDMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< DMatTDMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< DMatTDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct DMatDVecMultExprTrait< DMatTDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector > + , DMatDVecMultExprTrait_< MT1, TDMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct DMatSVecMultExprTrait< DMatTDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector > + , DMatDVecMultExprTrait_< MT1, TDMatSVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecDMatMultExprTrait< VT, DMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDVecTDMatMultExprTrait_< TDVecDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecDMatMultExprTrait< VT, DMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDVecTDMatMultExprTrait_< TSVecDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< DMatTDMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< DMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< DMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense matrix expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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::value || RequiresEvaluation::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 This; //!< Type of this DMatTDMatSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side dense matrix expression. + typedef If_< IsExpression, 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::value && ( RequiresEvaluation::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) || + ( IsExpression::value && ( RequiresEvaluation::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 > + assign( DenseMatrix& 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 // Storage order of the target dense matrix + friend inline EnableIf_< UseAssign > + assign( DenseMatrix& 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::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& 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_ ); + + 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 > + addAssign( DenseMatrix& 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 // Storage order of the target dense matrix + friend inline EnableIf_< UseAssign > + addAssign( DenseMatrix& 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 > + subAssign( DenseMatrix& 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 // Storage order of the target dense matrix + friend inline EnableIf_< UseAssign > + subAssign( DenseMatrix& 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 > + smpAssign( DenseMatrix& 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::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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A, C; + blaze::DynamicMatrix 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 >, Not< IsSymmetric > > + , const DMatTDMatSubExpr > + operator-( const DenseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatTDMatSubExpr( ~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 A; + blaze::DynamicMatrix 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 >, Not< IsSymmetric > > + , const DMatTDMatSubExpr > + operator-( const DenseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatTDMatSubExpr( ~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, Not< IsSymmetric > >, const SubExprTrait_ > + operator-( const DenseMatrix& lhs, const DenseMatrix& 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, const SubExprTrait_ > + operator-( const DenseMatrix& lhs, const DenseMatrix& 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 >, IsSymmetric >, const SubExprTrait_ > + operator-( const DenseMatrix& lhs, const DenseMatrix& 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, const SubExprTrait_ > + operator-( const DenseMatrix& lhs, const DenseMatrix& 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 > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< DMatTDMatSubExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsAligned< DMatTDMatSubExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< DMatTDMatSubExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< DMatTDMatSubExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< DMatTDMatSubExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< DMatTDMatSubExpr > + : public BoolConstant< And< IsUniLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< DMatTDMatSubExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< DMatTDMatSubExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< DMatTDMatSubExpr > + : public BoolConstant< And< IsUniUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< DMatTDMatSubExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< DMatTDMatSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< DMatTDMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< DMatTDMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatAddExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense matrix expression. + typedef ReturnType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef AddExprTrait_ 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 This; //!< Type of this DMatTSMatAddExpr instance. + typedef AddTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::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& 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::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& 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_ ); + + 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& 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& 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 > + smpAssign( DenseMatrix& 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::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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A, C; + blaze::CompressedMatrix 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 + operator+( const DenseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatTSMatAddExpr( ~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 A; + blaze::DynamicMatrix 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 + operator+( const SparseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatTSMatAddExpr( ~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, T3 > + operator+( const DMatTSMatAddExpr& lhs, const DenseMatrix& 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, T3 > + operator-( const DMatTSMatAddExpr& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return ( lhs.leftOperand() - (~rhs) ) + lhs.rightOperand(); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< DMatTSMatAddExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< DMatTSMatAddExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< DMatTSMatAddExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< DMatTSMatAddExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< DMatTSMatAddExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< DMatTSMatAddExpr > + : public BoolConstant< Or< And< IsUniLower, IsStrictlyLower > + , And< IsUniLower, IsStrictlyLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< DMatTSMatAddExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< DMatTSMatAddExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< DMatTSMatAddExpr > + : public BoolConstant< Or< And< IsUniUpper, IsStrictlyUpper > + , And< IsUniUpper, IsStrictlyUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< DMatTSMatAddExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatAddExprTrait< DMatTSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatTSMatAddExprTrait_< DMatDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatAddExprTrait< DMatTSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , DMatTSMatAddExprTrait_< DMatTDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatSubExprTrait< DMatTSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatTSMatAddExprTrait_< DMatDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatSubExprTrait< DMatTSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , DMatTSMatAddExprTrait_< DMatTDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< DMatTSMatAddExpr, AF > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< DMatTSMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< DMatTSMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side sparse matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::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::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::value && + !IsResizable< ElementType_ >::value && + !IsResizable::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DMatTSMatMultExpr This; //!< Type of this DMatTSMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 > + assign( DenseMatrix& 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 > + selectAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsRowMajorMatrix::value ? B.columns() : 256UL ); + + for( size_t jj=0UL; jj::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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 > + selectAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsRowMajorMatrix::value ? B.columns() : 256UL ); + + reset( C ); + + for( size_t jj=0UL; jj::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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 > + assign( SparseMatrix& 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_ ); + + 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 > + assign( Matrix& 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 > + addAssign( DenseMatrix& 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 > + selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsRowMajorMatrix::value ? B.columns() : 256UL ); + + for( size_t jj=0UL; jj::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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 > + selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsRowMajorMatrix::value ? B.columns() : 256UL ); + + for( size_t jj=0UL; jj::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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 > + addAssign( Matrix& 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 > + subAssign( DenseMatrix& 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 > + selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsRowMajorMatrix::value ? B.columns() : 256UL ); + + for( size_t jj=0UL; jj::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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 > + selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsRowMajorMatrix::value ? B.columns() : 256UL ); + + for( size_t jj=0UL; jj::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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::value ) + ?( IsStrictlyUpper::value ? B.upperBound(i,j) : B.lowerBound(i,j) ) + :( B.begin(j) ) ); + const ConstIterator end( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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 > + subAssign( Matrix& 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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAssign( Matrix& 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 > + smpAddAssign( DenseMatrix& 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 > + smpAddAssign( Matrix& 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 > + smpSubAssign( DenseMatrix& 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 > + smpSubAssign( Matrix& 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 A, C; + blaze::CompressedMatrix 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 + operator*( const DenseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatTSMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< DMatTSMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< DMatTSMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsAligned< DMatTSMatMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< DMatTSMatMultExpr > + : public BoolConstant< IsLower::value && IsLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< DMatTSMatMultExpr > + : public BoolConstant< IsUniLower::value && IsUniLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< DMatTSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< DMatTSMatMultExpr > + : public BoolConstant< IsUpper::value && IsUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< DMatTSMatMultExpr > + : public BoolConstant< IsUniUpper::value && IsUniUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< DMatTSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct DMatDVecMultExprTrait< DMatTSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector > + , DMatDVecMultExprTrait_< MT1, TSMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct DMatSVecMultExprTrait< DMatTSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector > + , DMatSVecMultExprTrait_< MT1, TSMatSVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecDMatMultExprTrait< VT, DMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , TDVecTSMatMultExprTrait_< TDVecDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecDMatMultExprTrait< VT, DMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , TDVecTSMatMultExprTrait_< TSVecDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< DMatTSMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< DMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< DMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense matrix expression. + typedef ReturnType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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 This; //!< Type of this DMatTSMatSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::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& 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::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& 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_ ); + + 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& 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& 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 > + smpAssign( DenseMatrix& 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::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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A, C; + blaze::CompressedMatrix 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 + operator-( const DenseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return DMatTSMatSubExpr( ~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, T3 > + operator+( const DMatTSMatSubExpr& lhs, const DenseMatrix& 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, T3 > + operator-( const DMatTSMatSubExpr& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return ( lhs.leftOperand() - (~rhs) ) - lhs.rightOperand(); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< DMatTSMatSubExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< DMatTSMatSubExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< DMatTSMatSubExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< DMatTSMatSubExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< DMatTSMatSubExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< DMatTSMatSubExpr > + : public BoolConstant< And< IsUniLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< DMatTSMatSubExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< DMatTSMatSubExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< DMatTSMatSubExpr > + : public BoolConstant< And< IsUniUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< DMatTSMatSubExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatAddExprTrait< DMatTSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatTSMatSubExprTrait_< DMatDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatAddExprTrait< DMatTSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , DMatTSMatSubExprTrait_< DMatTDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatSubExprTrait< DMatTSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatTSMatSubExprTrait_< DMatDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatSubExprTrait< DMatTSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , DMatTSMatSubExprTrait_< DMatTDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< DMatTSMatSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< DMatTSMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< DMatTSMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatTransExpr + , private If< IsComputation, Computation, EmptyType >::Type +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the dense matrix expression. + typedef CompositeType_ 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::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 This; //!< Type of this DMatTransExpr instance. + typedef TransposeType_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef ResultType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ 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, 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_ 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::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 > + assign( DenseMatrix& 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 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 > + assign( SparseMatrix& 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_ ); + + 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 > + addAssign( DenseMatrix& 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 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 > + subAssign( DenseMatrix& 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 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 > + smpAssign( DenseMatrix& 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 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 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 > + smpSubAssign( DenseMatrix& 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 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 A; + blaze::DynamicMatrix B; + // ... Resizing and initialization + B = trans( A ); + \endcode +*/ +template< typename MT // Type of the dense matrix + , bool SO > // Storage order +inline const DMatTransExpr trans( const DenseMatrix& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return DMatTransExpr( ~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 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::Operand trans( const DMatTransExpr& dm ) +{ + BLAZE_FUNCTION_TRACE; + + return dm.operand(); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct Rows< DMatTransExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct Columns< DMatTransExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsAligned< DMatTransExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsPadded< DMatTransExpr > + : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsSymmetric< DMatTransExpr > + : public BoolConstant< IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsHermitian< DMatTransExpr > + : public BoolConstant< IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsLower< DMatTransExpr > + : public BoolConstant< IsUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUniLower< DMatTransExpr > + : public BoolConstant< IsUniUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsStrictlyLower< DMatTransExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUpper< DMatTransExpr > + : public BoolConstant< IsLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUniUpper< DMatTransExpr > + : public BoolConstant< IsUniLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsStrictlyUpper< DMatTransExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct DMatTransExprTrait< DMatTransExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix > + , Operand_< DMatTransExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TDMatTransExprTrait< DMatTransExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix > + , Operand_< DMatTransExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool AF > +struct SubmatrixExprTrait< DMatTransExpr, AF > +{ + public: + //********************************************************************************************** + using Type = TransExprTrait_< SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct RowExprTrait< DMatTransExpr > +{ + public: + //********************************************************************************************** + using Type = TransExprTrait_< ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct ColumnExprTrait< DMatTransExpr > +{ + public: + //********************************************************************************************** + using Type = TransExprTrait_< RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > +{ + public: + //**Type definitions**************************************************************************** + typedef DMatTransposer This; //!< Type of this DMatTransposer instance. + typedef TransposeType_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef ResultType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the matrix elements. + typedef SIMDTrait_ SIMDType; //!< SIMD type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef Reference_ Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant matrix value. + typedef ConstPointer_ ConstPointer; //!< Pointer to a constant matrix value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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, 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, 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& 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 // Type of the right-hand side dense matrix + inline void assign( const DenseMatrix& 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 // Type of the right-hand side sparse matrix + inline void assign( const SparseMatrix& 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_ 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& 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_ 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& 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 // Type of the right-hand side dense matrix + inline void addAssign( const DenseMatrix& 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 // Type of the right-hand side sparse matrix + inline void addAssign( const SparseMatrix& 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_ 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& 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_ 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& 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 // Type of the right-hand side dense matrix + inline void subAssign( const DenseMatrix& 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 // Type of the right-hand side sparse matrix + inline void subAssign( const SparseMatrix& 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_ 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& 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_ 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 : public DenseMatrix< DMatTransposer, true > +{ + public: + //**Type definitions**************************************************************************** + typedef DMatTransposer This; //!< Type of this DMatTransposer instance. + typedef TransposeType_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef ResultType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the matrix elements. + typedef SIMDTrait_ SIMDType; //!< SIMD type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef Reference_ Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant matrix value. + typedef ConstPointer_ ConstPointer; //!< Pointer to a constant matrix value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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, 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, 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& 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 // Type of the right-hand side dense matrix + inline void assign( const DenseMatrix& 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 // Type of the right-hand side sparse matrix + inline void assign( const SparseMatrix& 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_ 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& 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_ 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& 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 // Type of the right-hand side dense matrix + inline void addAssign( const DenseMatrix& 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 // Type of the right-hand side sparse matrix + inline void addAssign( const SparseMatrix& 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_ 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& 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_ 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& 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 // Type of the right-hand side dense matrix + inline void subAssign( const DenseMatrix& 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 // Type of the right-hand side sparse matrix + inline void subAssign( const SparseMatrix& 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_ 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& 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_ 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& 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& m ) noexcept +{ + return m.isIntact(); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct HasMutableDataAccess< DMatTransposer > + : public BoolConstant< HasMutableDataAccess::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsAligned< DMatTransposer > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsPadded< DMatTransposer > + : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct SubmatrixTrait< DMatTransposer > +{ + using Type = SubmatrixTrait_< ResultType_< DMatTransposer > >; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecVecAddExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RE1; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ RE2; //!< Result type of the right-hand side dense vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side dense vector expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense vector expression. + typedef ElementType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef AddExprTrait_ 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::value || RequiresEvaluation::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 This; //!< Type of this DVecDVecAddExpr instance. + typedef AddTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, 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_ LeftIteratorType; + + //! ConstIterator type of the right-hand side dense vector expression. + typedef ConstIterator_ 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::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::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::value && ( RequiresEvaluation::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) || + ( IsExpression::value && ( RequiresEvaluation::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 > + assign( DenseVector& lhs, const DVecDVecAddExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + if( !IsComputation::value && isSame( ~lhs, rhs.lhs_ ) ) { + addAssign( ~lhs, rhs.rhs_ ); + } + else if( !IsComputation::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 > + assign( SparseVector& 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_ ); + + 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 > + addAssign( DenseVector& 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 > + subAssign( DenseVector& 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 > + multAssign( DenseVector& 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_ ); + + 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 > + divAssign( DenseVector& 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_ ); + + 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 > + smpAssign( DenseVector& lhs, const DVecDVecAddExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + if( !IsComputation::value && isSame( ~lhs, rhs.lhs_ ) ) { + smpAddAssign( ~lhs, rhs.rhs_ ); + } + else if( !IsComputation::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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 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 + operator+( const DenseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + return DVecDVecAddExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct Size< DVecDVecAddExpr > + : public Max< Size, Size > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct IsAligned< DVecDVecAddExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct IsPadded< DVecDVecAddExpr > + : public BoolConstant< And< IsPadded, IsPadded >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< DVecDVecAddExpr, AF > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private CrossExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side dense vector expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense vector expression. + typedef ElementType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_< MultExprTrait_, MultExprTrait_ > ExprReturnType; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DVecDVecCrossExpr This; //!< Type of this DVecDVecCrossExpr instance. + typedef CrossTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, const VT2, const VT2& > RightOperand; + + //! Composite type of the left-hand side dense vector expression. + typedef If_< IsComputation, const StaticVector, CT1 > LT; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsComputation, const StaticVector, 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& 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& 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_ ); + + 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& 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& 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& 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& 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 a( 3UL ), b( 3UL ); + blaze::StaticVector 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 + operator%( const DenseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != 3UL || (~rhs).size() != 3UL ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid vector size for cross product" ); + } + + return DVecDVecCrossExpr( ~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 a( 3UL ), b( 3UL ); + blaze::StaticVector 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 + cross( const DenseVector& lhs, const DenseVector& rhs ) +{ + return lhs % rhs; +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct Size< DVecDVecCrossExpr > : 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecVecDivExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side dense vector expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense vector expression. + typedef ElementType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef DivExprTrait_ 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::value || RequiresEvaluation::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 This; //!< Type of this DVecDVecDivExpr instance. + typedef DivTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, 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_ LeftIteratorType; + + //! ConstIterator type of the right-hand side dense vector expression. + typedef ConstIterator_ 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::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::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::value && ( RequiresEvaluation::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) || + ( IsExpression::value && ( RequiresEvaluation::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 > + assign( DenseVector& lhs, const DVecDVecDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + if( !IsComputation::value && isSame( ~lhs, rhs.lhs_ ) ) { + divAssign( ~lhs, rhs.rhs_ ); + } + else if( IsSame::value || + IsSame< ElementType_, ElementType_ >::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 > + assign( SparseVector& 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_ ); + + 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 > + addAssign( DenseVector& 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_ ); + + 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 > + subAssign( DenseVector& 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_ ); + + 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 > + multAssign( DenseVector& 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_ ); + + 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 > + divAssign( DenseVector& 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_ ); + + 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 > + smpAssign( DenseVector& lhs, const DVecDVecDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + if( !IsComputation::value && isSame( ~lhs, rhs.lhs_ ) ) { + smpDivAssign( ~lhs, rhs.rhs_ ); + } + else if( IsSame::value || + IsSame< ElementType_, ElementType_ >::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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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_ ); + + 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 > + smpSubAssign( DenseVector& 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_ ); + + 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 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 + operator/( const DenseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + return DVecDVecDivExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct Size< DVecDVecDivExpr > + : public Max< Size, Size > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct IsAligned< DVecDVecDivExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< DVecDVecDivExpr, AF > +{ + public: + //********************************************************************************************** + using Type = DivExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side dense vector expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense vector expression. + typedef ElementType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef MultExprTrait_ 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::value || RequiresEvaluation::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 This; //!< Type of this DVecDVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, 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_ LeftIteratorType; + + //! ConstIterator type of the right-hand side dense vector expression. + typedef ConstIterator_ 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::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::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::value && ( RequiresEvaluation::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) || + ( IsExpression::value && ( RequiresEvaluation::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 > + assign( DenseVector& lhs, const DVecDVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + if( !IsComputation::value && isSame( ~lhs, rhs.lhs_ ) ) { + multAssign( ~lhs, rhs.rhs_ ); + } + else if( !IsComputation::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 > + assign( SparseVector& 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_ ); + + 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 > + addAssign( DenseVector& 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_ ); + + 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 > + subAssign( DenseVector& 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_ ); + + 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 > + multAssign( DenseVector& 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 > + multAssign( SparseVector& 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 > + divAssign( DenseVector& 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_ ); + + 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 > + smpAssign( DenseVector& lhs, const DVecDVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + if( !IsComputation::value && isSame( ~lhs, rhs.lhs_ ) ) { + smpMultAssign( ~lhs, rhs.rhs_ ); + } + else if( !IsComputation::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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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_ ); + + 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 > + smpSubAssign( DenseVector& 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_ ); + + 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 > + smpMultAssign( DenseVector& 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 > + smpMultAssign( SparseVector& 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 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 + operator*( const DenseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + return DVecDVecMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct Size< DVecDVecMultExpr > + : public Max< Size, Size > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct IsAligned< DVecDVecMultExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct IsPadded< DVecDVecMultExpr > + : public BoolConstant< And< IsPadded, IsPadded >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< DVecDVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecVecSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side dense vector expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense vector expression. + typedef ElementType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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::value || RequiresEvaluation::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 This; //!< Type of this DVecDVecSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, 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_ LeftIteratorType; + + //! ConstIterator type of the right-hand side dense vector expression. + typedef ConstIterator_ 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::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::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::value && ( RequiresEvaluation::value ? lhs_.isAliased( alias ) : lhs_.canAlias( alias ) ) ) || + ( IsExpression::value && ( RequiresEvaluation::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 > + assign( DenseVector& lhs, const DVecDVecSubExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + if( !IsComputation::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 > + assign( SparseVector& 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_ ); + + 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 > + addAssign( DenseVector& 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 > + subAssign( DenseVector& 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 > + multAssign( DenseVector& 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_ ); + + 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 > + divAssign( DenseVector& 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_ ); + + 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 > + smpAssign( DenseVector& lhs, const DVecDVecSubExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + if( !IsComputation::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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 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 + operator-( const DenseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + return DVecDVecSubExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct Size< DVecDVecSubExpr > + : public Max< Size, Size > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct IsAligned< DVecDVecSubExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct IsPadded< DVecDVecSubExpr > + : public BoolConstant< And< IsPadded, IsPadded >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< DVecDVecSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecEvalExpr + , private Computation +{ + public: + //**Type definitions**************************************************************************** + typedef DVecEvalExpr This; //!< Type of this DVecEvalExpr instance. + typedef ResultType_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ 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, 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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 a, b; + // ... Resizing and initialization + b = eval( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecEvalExpr eval( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecEvalExpr( ~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 eval( const DVecEvalExpr& dv ) +{ + return dv; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct Size< DVecEvalExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct IsAligned< DVecEvalExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct DVecEvalExprTrait< DVecEvalExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector > + , DVecEvalExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TDVecEvalExprTrait< DVecEvalExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector > + , DVecEvalExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF, bool AF > +struct SubvectorExprTrait< DVecEvalExpr, AF > +{ + public: + //********************************************************************************************** + using Type = EvalExprTrait_< SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecForEachExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the dense vector expression. + typedef ElementType_ ET; //!< Element type of the dense vector expression. + typedef ReturnType_ 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::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() }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DVecForEachExpr This; //!< Type of this DVecForEachExpr instance. + typedef ForEachTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + + //! Return type for expression template evaluations. + typedef decltype( std::declval()( std::declval() ) ) 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, 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_ 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, UseSIMDEnabledFlag, HasLoad >::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::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::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 + , IsSame< UnderlyingNumeric, UnderlyingNumeric > > > + assign( DenseVector& 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 + , Not< IsSame< UnderlyingNumeric, UnderlyingNumeric > > > > + assign( DenseVector& 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_ ); + + 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 > + assign( SparseVector& 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_ ); + + 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 > + addAssign( DenseVector& 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_ ); + + 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 > + subAssign( DenseVector& 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_ ); + + 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 > + multAssign( DenseVector& 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_ ); + + 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 > + divAssign( DenseVector& 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_ ); + + 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 + , IsSame< UnderlyingNumeric, UnderlyingNumeric > > > + smpAssign( DenseVector& 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 + , Not< IsSame< UnderlyingNumeric, UnderlyingNumeric > > > > + smpAssign( DenseVector& 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_ ); + + 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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_ ); + + 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 > + smpSubAssign( DenseVector& 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_ ); + + 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 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 forEach( const DenseVector& dv, OP op ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = abs( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr abs( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = floor( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr floor( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = ceil( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr ceil( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 > a, b; + // ... Resizing and initialization + b = conj( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr conj( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 > 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_ ctrans( const DenseVector& 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 a, b; + // ... Resizing and initialization + b = real( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr real( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = imag( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr imag( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 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 sqrt( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 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 invsqrt( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 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 cbrt( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 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 invcbrt( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 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,TF> pow( const DenseVector& dv, ET exp ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ET ); + + return DVecForEachExpr,TF>( ~dv, Pow( 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 a, b; + // ... Resizing and initialization + b = exp( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr exp( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 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 log( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 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 log10( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = sin( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr sin( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 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 asin( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = sinh( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr sinh( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = asinh( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr asinh( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = cos( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr cos( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 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 acos( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = cosh( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr cosh( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 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 acosh( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = tan( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr tan( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = atan( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr atan( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 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 tanh( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 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 atanh( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = erf( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr erf( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = erfc( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecForEachExpr erfc( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecForEachExpr( ~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& abs( const DVecForEachExpr& 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& floor( const DVecForEachExpr& 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& ceil( const DVecForEachExpr& 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 > 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::Operand conj( const DVecForEachExpr& 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 > 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 conj( const DVecTransExpr,!TF>& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecTransExpr( 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& real( const DVecForEachExpr& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return dv; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename OP, bool TF > +struct Size< DVecForEachExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename OP, bool TF > +struct IsAligned< DVecForEachExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename OP, bool TF > +struct IsPadded< DVecForEachExpr > + : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct DVecForEachExprTrait< DVecForEachExpr, Abs > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector > + , DVecForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TDVecForEachExprTrait< DVecForEachExpr, Abs > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector > + , DVecForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct DVecForEachExprTrait< DVecForEachExpr, Floor > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector > + , DVecForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TDVecForEachExprTrait< DVecForEachExpr, Floor > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector > + , DVecForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct DVecForEachExprTrait< DVecForEachExpr, Ceil > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector > + , DVecForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TDVecForEachExprTrait< DVecForEachExpr, Ceil > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector > + , DVecForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct DVecForEachExprTrait< DVecForEachExpr, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector > + , Operand_< DVecForEachExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TDVecForEachExprTrait< DVecForEachExpr, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector > + , Operand_< DVecForEachExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct DVecForEachExprTrait< DVecTransExpr< DVecForEachExpr, false >, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector > + , DVecTransExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TDVecForEachExprTrait< DVecTransExpr< DVecForEachExpr, true >, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector > + , DVecTransExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct DVecForEachExprTrait< DVecForEachExpr, Real > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector > + , DVecForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TDVecForEachExprTrait< DVecForEachExpr, Real > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector > + , DVecForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename OP, bool TF, bool AF > +struct SubvectorExprTrait< DVecForEachExpr, AF > +{ + public: + //********************************************************************************************** + using Type = ForEachExprTrait_< SubvectorExprTrait_, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecVecAddExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side sparse vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side sparse vector expression. + typedef TransposeType_ TT1; //!< Transpose type of the left-hand side dense vector expression. + typedef TransposeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef AddExprTrait_ 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 This; //!< Type of this DVecSVecAddExpr instance. + typedef AddTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side sparse vector expression. + typedef If_< IsExpression, 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::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& lhs, const DVecSVecAddExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + if( !IsComputation::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& 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_ ); + + 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& 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& 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& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& lhs, const DVecSVecAddExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + if( !IsComputation::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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 a, c; + blaze::CompressedVector 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 + operator+( const DenseVector& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + return DVecSVecAddExpr( ~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 a; + blaze::DynamicVector 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 + operator+( const SparseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + return DVecSVecAddExpr( ~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, T3 > + operator+( const DVecSVecAddExpr& lhs, const DenseVector& 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, T3 > + operator-( const DVecSVecAddExpr& lhs, const DenseVector& 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 > + : public Max< Size, Size > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename VT3 > +struct DVecDVecAddExprTrait< DVecSVecAddExpr, VT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseVector, IsColumnVector + , IsSparseVector, IsColumnVector + , IsDenseVector, IsColumnVector > + , DVecSVecAddExprTrait_< DVecDVecAddExprTrait_, VT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename VT3 > +struct TDVecTDVecAddExprTrait< DVecSVecAddExpr, VT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseVector, IsRowVector + , IsDenseVector, IsRowVector > + , TDVecTSVecAddExprTrait_< TDVecTDVecAddExprTrait_, VT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename VT3 > +struct DVecDVecSubExprTrait< DVecSVecAddExpr, VT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseVector, IsColumnVector + , IsSparseVector, IsColumnVector + , IsDenseVector, IsColumnVector > + , DVecSVecAddExprTrait_< DVecDVecSubExprTrait_, VT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename VT3 > +struct TDVecTDVecSubExprTrait< DVecSVecAddExpr, VT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseVector, IsRowVector + , IsDenseVector, IsRowVector > + , TDVecTSVecAddExprTrait_< TDVecTDVecSubExprTrait_, VT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< DVecSVecAddExpr, AF > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private CrossExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side sparse vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side sparse vector expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense vector expression. + typedef ElementType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_< MultExprTrait_, MultExprTrait_ > ExprReturnType; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DVecSVecCrossExpr This; //!< Type of this DVecSVecCrossExpr instance. + typedef CrossTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side sparse vector expression. + typedef If_< IsExpression, const VT2, const VT2& > RightOperand; + + //! Composite type of the left-hand side dense vector expression. + typedef If_< IsComputation, const StaticVector, CT1 > LT; + + //! Composite type of the right-hand side sparse vector expression. + typedef const StaticVector 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& 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& 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_ ); + + 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& 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& 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& 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& 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 a( 3UL ); + blaze::CompressedVector b( 3UL ); + blaze::StaticVector 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 + operator%( const DenseVector& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != 3UL || (~rhs).size() != 3UL ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid vector size for cross product" ); + } + + return DVecSVecCrossExpr( ~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 a( 3UL ); + blaze::CompressedVector b( 3UL ); + blaze::StaticVector 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 + cross( const DenseVector& lhs, const SparseVector& rhs ) +{ + return lhs % rhs; +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct Size< DVecSVecCrossExpr > : 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side sparse vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side sparse vector expression. + typedef TransposeType_ TT1; //!< Transpose type of the left-hand side dense vector expression. + typedef TransposeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef MultExprTrait_ 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::value || RequiresEvaluation::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 This; //!< Type of this DVecSVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side sparse vector expression. + typedef If_< IsExpression, 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 Element; + + //! Iterator type of the sparse vector expression. + typedef ConstIterator_< RemoveReference_ > 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 > + assign( DenseVector& lhs, const DVecSVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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 > + assign( SparseVector& lhs, const DVecSVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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 > + addAssign( DenseVector& lhs, const DVecSVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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 > + subAssign( DenseVector& lhs, const DVecSVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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 > + multAssign( DenseVector& lhs, const DVecSVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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( ; ivalue(); + ++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 a; + blaze::CompressedVector 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 + operator*( const DenseVector& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + return DVecSVecMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct Size< DVecSVecMultExpr > + : public Max< Size, Size > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< DVecSVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecVecSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side sparse vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side sparse vector expression. + typedef TransposeType_ TT1; //!< Transpose type of the left-hand side dense vector expression. + typedef TransposeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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 This; //!< Type of this DVecSVecSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side sparse vector expression. + typedef If_< IsExpression, 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::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& lhs, const DVecSVecSubExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + if( !IsComputation::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& 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_ ); + + 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& 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& 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& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& lhs, const DVecSVecSubExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + if( !IsComputation::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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 a, c; + blaze::CompressedVector 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 + operator-( const DenseVector& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + return DVecSVecSubExpr( ~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, T3 > + operator+( const DVecSVecSubExpr& lhs, const DenseVector& 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, T3 > + operator-( const DVecSVecSubExpr& lhs, const DenseVector& 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 > + : public Max< Size, Size > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename VT3 > +struct DVecDVecAddExprTrait< DVecSVecSubExpr, VT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseVector, IsColumnVector + , IsSparseVector, IsColumnVector + , IsDenseVector, IsColumnVector > + , DVecSVecSubExprTrait_< DVecDVecAddExprTrait_, VT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename VT3 > +struct TDVecTDVecAddExprTrait< DVecSVecSubExpr, VT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseVector, IsRowVector + , IsDenseVector, IsRowVector > + , TDVecTSVecSubExprTrait_< TDVecTDVecAddExprTrait_, VT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename VT3 > +struct DVecDVecSubExprTrait< DVecSVecSubExpr, VT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseVector, IsColumnVector + , IsSparseVector, IsColumnVector + , IsDenseVector, IsColumnVector > + , DVecSVecSubExprTrait_< DVecDVecSubExprTrait_, VT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename VT3 > +struct TDVecTDVecSubExprTrait< DVecSVecSubExpr, VT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseVector, IsRowVector + , IsDenseVector, IsRowVector > + , TDVecTSVecSubExprTrait_< TDVecTDVecSubExprTrait_, VT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< DVecSVecSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecScalarDivExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the dense vector expression. + typedef ReturnType_ RN; //!< Return type of the dense vector expression. + typedef ElementType_ ET; //!< Element type of the dense vector expression. + typedef CompositeType_ 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::value }; + + //! Expression return type for the subscript operator. + typedef DivExprTrait_ 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::value && RequiresEvaluation::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 This; //!< Type of this DVecScalarDivExpr instance. + typedef DivTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, 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_ 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::value && + ( HasSIMDDiv::value || + HasSIMDDiv,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::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::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 > + assign( DenseVector& 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 > + assign( SparseVector& 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 > + addAssign( DenseVector& 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_ ); + + 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 > + subAssign( DenseVector& 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_ ); + + 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 > + multAssign( DenseVector& 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_ ); + + 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 > + divAssign( DenseVector& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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 > + smpAddAssign( DenseVector& 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_ ); + + 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 > + smpSubAssign( DenseVector& 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_ ); + + 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 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, DivExprTrait_ > + operator/( const DenseVector& vec, T2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_USER_ASSERT( scalar != T2(0), "Division by zero detected" ); + + typedef DivExprTrait_ ReturnType; + typedef RightOperand_ ScalarType; + + if( IsMultExpr::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, Or< IsInvertible, IsInvertible > > + , MultExprTrait_< DVecScalarDivExpr, ST2 > > + operator*( const DVecScalarDivExpr& 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, Or< IsInvertible, IsInvertible > > + , MultExprTrait_< ST1, DVecScalarDivExpr > > + operator*( ST1 scalar, const DVecScalarDivExpr& 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 + , DivExprTrait_< VT, MultTrait_ > > + operator/( const DVecScalarDivExpr& vec, ST2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_USER_ASSERT( scalar != ST2(0), "Division by zero detected" ); + + typedef MultTrait_ MultType; + typedef DivExprTrait_ ReturnType; + typedef RightOperand_ ScalarType; + + if( IsMultExpr::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 > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST, bool TF > +struct IsAligned< DVecScalarDivExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST, bool TF > +struct IsPadded< DVecScalarDivExpr > + : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DVECSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename ST2 > +struct DVecScalarMultExprTrait< DVecScalarDivExpr, ST2 > +{ + private: + //********************************************************************************************** + typedef DivTrait_ ScalarType; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsNumeric, IsNumeric > + , If_< IsInvertible + , DVecScalarMultExprTrait_ + , DVecScalarMultExpr< DVecScalarDivExpr, ST2, false > > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDVECSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename ST2 > +struct TDVecScalarMultExprTrait< DVecScalarDivExpr, ST2 > +{ + private: + //********************************************************************************************** + typedef DivTrait_ ScalarType; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsNumeric, IsNumeric > + , If_< IsInvertible + , DVecScalarMultExprTrait_ + , DVecScalarMultExpr< DVecScalarDivExpr, ST2, true > > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTOREXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST, bool TF, bool AF > +struct SubvectorExprTrait< DVecScalarDivExpr, AF > +{ + public: + //********************************************************************************************** + using Type = DivExprTrait_< SubvectorExprTrait_, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecScalarMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the dense vector expression. + typedef ReturnType_ RN; //!< Return type of the dense vector expression. + typedef ElementType_ ET; //!< Element type of the dense vector expression. + typedef CompositeType_ 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::value }; + + //! Expression return type for the subscript operator. + typedef MultExprTrait_ 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::value && RequiresEvaluation::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 This; //!< Type of this DVecScalarMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, 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_ 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::value && + ( HasSIMDMult::value || + HasSIMDMult,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::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::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 > + assign( DenseVector& 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 > + assign( SparseVector& 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 > + addAssign( DenseVector& 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_ ); + + 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 > + subAssign( DenseVector& 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_ ); + + 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 > + multAssign( DenseVector& 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_ ); + + 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 > + divAssign( DenseVector& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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 > + smpAddAssign( DenseVector& 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_ ); + + 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 > + smpSubAssign( DenseVector& 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_ ); + + 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 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,TF> + operator-( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + typedef UnderlyingBuiltin_ ElementType; + return DVecScalarMultExpr( ~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 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, MultExprTrait_ > + operator*( const DenseVector& vec, T2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + return MultExprTrait_( ~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 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, MultExprTrait_ > + operator*( T1 scalar, const DenseVector& vec ) +{ + BLAZE_FUNCTION_TRACE; + + return MultExprTrait_( ~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 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,TF> + normalize( const DenseVector& vec ) +{ + typedef ElementType_ 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( ~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 + operator-( const DVecScalarMultExpr& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecScalarMultExpr( 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, MultExprTrait_< DVecScalarMultExpr, ST2 > > + operator*( const DVecScalarMultExpr& 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, MultExprTrait_< ST1, DVecScalarMultExpr > > + operator*( ST1 scalar, const DVecScalarMultExpr& 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, Or< IsInvertible, IsInvertible > > + , DivExprTrait_< DVecScalarMultExpr, ST2 > > + operator/( const DVecScalarMultExpr& 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, VT2 > + operator*( const DVecScalarMultExpr& lhs, const DenseVector& 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 > + operator*( const DenseVector& lhs, const DVecScalarMultExpr& 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, DVecScalarMultExpr > + operator*( const DVecScalarMultExpr& lhs, const DVecScalarMultExpr& 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, VT2 > + operator*( const DVecScalarMultExpr& lhs, const DenseVector& 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 > + operator*( const DenseVector& lhs, const DVecScalarMultExpr& 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, DVecScalarMultExpr > + operator*( const DVecScalarMultExpr& lhs, const DVecScalarMultExpr& 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, VT2 > + operator*( const DVecScalarMultExpr& lhs, const SparseVector& 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 > + operator*( const SparseVector& lhs, const DVecScalarMultExpr& 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, SVecScalarMultExpr > + operator*( const DVecScalarMultExpr& lhs, const SVecScalarMultExpr& 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, DVecScalarMultExpr > + operator*( const SVecScalarMultExpr& lhs, const DVecScalarMultExpr& 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, VT2 > + operator*( const DVecScalarMultExpr& lhs, const SparseVector& 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 > + operator*( const SparseVector& lhs, const DVecScalarMultExpr& 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, SVecScalarMultExpr > + operator*( const DVecScalarMultExpr& lhs, const SVecScalarMultExpr& 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, DVecScalarMultExpr > + operator*( const SVecScalarMultExpr& lhs, const DVecScalarMultExpr& 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 > + operator*( const DenseMatrix& mat, const DVecScalarMultExpr& 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, MT > + operator*( const DVecScalarMultExpr& vec, const DenseMatrix& 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 > + operator*( const SparseMatrix& mat, const DVecScalarMultExpr& 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, MT > + operator*( const DVecScalarMultExpr& vec, const SparseMatrix& 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 > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST, bool TF > +struct IsAligned< DVecScalarMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST, bool TF > +struct IsPadded< DVecScalarMultExpr > + : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DVECSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename ST2 > +struct DVecScalarMultExprTrait< DVecScalarMultExpr, ST2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsNumeric, IsNumeric > + , DVecScalarMultExprTrait_< VT, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDVECSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename ST2 > +struct TDVecScalarMultExprTrait< DVecScalarMultExpr, ST2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsNumeric, IsNumeric > + , TDVecScalarMultExprTrait_< VT, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DVECSCALARDIVEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename ST2 > +struct DVecScalarDivExprTrait< DVecScalarMultExpr, ST2 > +{ + private: + //********************************************************************************************** + typedef DivTrait_ ScalarType; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsNumeric, IsNumeric > + , If_< IsInvertible + , DVecScalarMultExprTrait_ + , DVecScalarDivExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDVECSCALARDIVEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename ST2 > +struct TDVecScalarDivExprTrait< DVecScalarMultExpr, ST2 > +{ + private: + //********************************************************************************************** + typedef DivTrait_ ScalarType; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsNumeric, IsNumeric > + , If_< IsInvertible + , TDVecScalarMultExprTrait_ + , TDVecScalarDivExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DVECDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST, typename VT2 > +struct DVecDVecMultExprTrait< DVecScalarMultExpr, VT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsDenseVector, IsColumnVector + , IsNumeric > + , DVecScalarMultExprTrait_< DVecDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename ST > +struct DVecDVecMultExprTrait< VT1, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsDenseVector, IsColumnVector + , IsNumeric > + , DVecScalarMultExprTrait_< DVecDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST1, typename VT2, typename ST2 > +struct DVecDVecMultExprTrait< DVecScalarMultExpr, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsDenseVector, IsColumnVector + , IsNumeric, IsNumeric > + , DVecScalarMultExprTrait_< DVecDVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DVECTDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST, typename VT2 > +struct DVecTDVecMultExprTrait< DVecScalarMultExpr, VT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsDenseVector, IsRowVector + , IsNumeric > + , DMatScalarMultExprTrait_< DVecTDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename ST > +struct DVecTDVecMultExprTrait< VT1, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsDenseVector, IsRowVector + , IsNumeric > + , DMatScalarMultExprTrait_< DVecTDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST1, typename VT2, typename ST2 > +struct DVecTDVecMultExprTrait< DVecScalarMultExpr, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsDenseVector, IsRowVector + , IsNumeric, IsNumeric > + , DMatScalarMultExprTrait_< DVecTDVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDVECTDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST, typename VT2 > +struct TDVecTDVecMultExprTrait< DVecScalarMultExpr, VT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseVector, IsRowVector + , IsNumeric > + , TDVecScalarMultExprTrait_< TDVecTDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename ST > +struct TDVecTDVecMultExprTrait< VT1, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseVector, IsRowVector + , IsNumeric > + , TDVecScalarMultExprTrait_< TDVecTDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST1, typename VT2, typename ST2 > +struct TDVecTDVecMultExprTrait< DVecScalarMultExpr, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseVector, IsRowVector + , IsNumeric, IsNumeric > + , TDVecScalarMultExprTrait_< TDVecTDVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DVECSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename ST > +struct DVecSVecMultExprTrait< DVecScalarMultExpr, VT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsSparseVector, IsColumnVector + , IsNumeric > + , SVecScalarMultExprTrait_< DVecSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST1, typename VT2, typename ST2 > +struct DVecSVecMultExprTrait< DVecScalarMultExpr, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsSparseVector, IsColumnVector + , IsNumeric, IsNumeric > + , SVecScalarMultExprTrait_< DVecSVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DVECTSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST, typename VT2 > +struct DVecTSVecMultExprTrait< DVecScalarMultExpr, VT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsSparseVector, IsRowVector + , IsNumeric > + , SMatScalarMultExprTrait_< DVecTSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST1, typename VT2, typename ST2 > +struct DVecTSVecMultExprTrait< DVecScalarMultExpr, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsSparseVector, IsRowVector + , IsNumeric, IsNumeric > + , SMatScalarMultExprTrait_< DVecTSVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDVECTSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST, typename VT2 > +struct TDVecTSVecMultExprTrait< DVecScalarMultExpr, VT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseVector, IsRowVector + , IsNumeric > + , TSVecScalarMultExprTrait_< TDVecTSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST1, typename VT2, typename ST2 > +struct TDVecTSVecMultExprTrait< DVecScalarMultExpr, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseVector, IsRowVector + , IsNumeric, IsNumeric > + , TSVecScalarMultExprTrait_< TDVecTSVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SVECDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename ST > +struct SVecDVecMultExprTrait< VT1, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector + , IsDenseVector, IsColumnVector + , IsNumeric > + , SVecScalarMultExprTrait_< SVecDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST1, typename VT2, typename ST2 > +struct SVecDVecMultExprTrait< SVecScalarMultExpr, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector + , IsDenseVector, IsColumnVector + , IsNumeric, IsNumeric > + , SVecScalarMultExprTrait_< SVecDVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SVECTDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename ST > +struct SVecTDVecMultExprTrait< VT1, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector + , IsDenseVector, IsRowVector + , IsNumeric > + , TSMatScalarMultExprTrait_< SVecTDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST1, typename VT2, typename ST2 > +struct SVecTDVecMultExprTrait< SVecScalarMultExpr, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector + , IsDenseVector, IsRowVector + , IsNumeric, IsNumeric > + , TSMatScalarMultExprTrait_< SVecTDVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSVECTDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename ST > +struct TSVecTDVecMultExprTrait< VT1, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseVector, IsRowVector + , IsNumeric > + , TSVecScalarMultExprTrait_< TSVecTDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST1, typename VT2, typename ST2 > +struct TSVecTDVecMultExprTrait< SVecScalarMultExpr, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseVector, IsRowVector + , IsNumeric, IsNumeric > + , TSVecScalarMultExprTrait_< TSVecTDVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DMATDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, typename ST > +struct DMatDVecMultExprTrait< MT, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsDenseVector, IsColumnVector + , IsNumeric > + , DVecScalarMultExprTrait_< DMatDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDMATDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, typename ST > +struct TDMatDVecMultExprTrait< MT, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector + , IsNumeric > + , DVecScalarMultExprTrait_< TDMatDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDVECDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, typename ST > +struct TDVecDMatMultExprTrait< DVecScalarMultExpr, MT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric > + , TDVecScalarMultExprTrait_< TDVecDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDVECTDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, typename ST > +struct TDVecTDMatMultExprTrait< DVecScalarMultExpr, MT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TDVecScalarMultExprTrait_< TDVecTDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SMATDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, typename ST > +struct SMatDVecMultExprTrait< MT, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseVector, IsColumnVector + , IsNumeric > + , DVecScalarMultExprTrait_< SMatDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSMATDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, typename ST > +struct TSMatDVecMultExprTrait< MT, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector + , IsNumeric > + , DVecScalarMultExprTrait_< TSMatDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDVECSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, typename ST > +struct TDVecSMatMultExprTrait< DVecScalarMultExpr, MT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric > + , TDVecScalarMultExprTrait_< TDVecSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDVECTSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, typename ST > +struct TDVecTSMatMultExprTrait< DVecScalarMultExpr, MT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TDVecScalarMultExprTrait_< TDVecTSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTOREXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST, bool TF, bool AF > +struct SubvectorExprTrait< DVecScalarMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecSerialExpr + , private Computation +{ + public: + //**Type definitions**************************************************************************** + typedef DVecSerialExpr This; //!< Type of this DVecSerialExpr instance. + typedef ResultType_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ 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, 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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 a, b; + // ... Resizing and initialization + b = serial( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecSerialExpr serial( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecSerialExpr( ~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 serial( const DVecSerialExpr& dv ) +{ + return dv; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct Size< DVecSerialExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct IsAligned< DVecSerialExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct DVecSerialExprTrait< DVecSerialExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector > + , DVecSerialExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TDVecSerialExprTrait< DVecSerialExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector > + , DVecSerialExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF, bool AF > +struct SubvectorExprTrait< DVecSerialExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SerialExprTrait_< SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private VecTVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense vector expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense vector expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side dense vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense vector expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef MultExprTrait_ 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_ + , ElementType_ + , ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::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::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DVecTDVecMultExpr This; //!< Type of this DVecTDVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, 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_ LeftIteratorType; + + //! ConstIterator type of the right-hand side dense matrix expression. + typedef ConstIterator_ 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::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::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 > + assign( DenseMatrix& 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 > + selectAssignKernel( DenseMatrix& 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 // Type of the right-hand side vector operand + static inline EnableIf_< UseVectorizedKernel > + selectAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + const size_t M( (~A).rows() ); + const size_t N( (~A).columns() ); + + const bool remainder( !IsPadded::value || !IsPadded::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 // Type of the target dense matrix + friend inline void assign( DenseMatrix& 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 > + selectAssignKernel( DenseMatrix& 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 // Type of the right-hand side vector operand + static inline EnableIf_< UseVectorizedKernel > + selectAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + const size_t M( (~A).rows() ); + const size_t N( (~A).columns() ); + + const bool remainder( !IsPadded::value || !IsPadded::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 // Storage order of the target sparse matrix + friend inline void assign( SparseMatrix& 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_ ); + + 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 > + addAssign( DenseMatrix& 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 > + selectAddAssignKernel( DenseMatrix& 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 // Type of the right-hand side vector operand + static inline EnableIf_< UseVectorizedKernel > + selectAddAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + const size_t M( (~A).rows() ); + const size_t N( (~A).columns() ); + + const bool remainder( !IsPadded::value || !IsPadded::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 // Type of the target dense matrix + friend inline void addAssign( DenseMatrix& 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 > + selectAddAssignKernel( DenseMatrix& 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 // Type of the right-hand side vector operand + static inline EnableIf_< UseVectorizedKernel > + selectAddAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + const size_t M( (~A).rows() ); + const size_t N( (~A).columns() ); + + const bool remainder( !IsPadded::value || !IsPadded::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 // Type of the target dense matrix + friend inline EnableIf_< UseAssign > + subAssign( DenseMatrix& 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 > + selectSubAssignKernel( DenseMatrix& 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 // Type of the right-hand side vector operand + static inline EnableIf_< UseVectorizedKernel > + selectSubAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + const size_t M( (~A).rows() ); + const size_t N( (~A).columns() ); + + const bool remainder( !IsPadded::value || !IsPadded::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 // Type of the target dense matrix + friend inline void subAssign( DenseMatrix& 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 > + selectSubAssignKernel( DenseMatrix& 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 // Type of the right-hand side vector operand + static inline EnableIf_< UseVectorizedKernel > + selectSubAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + const size_t M( (~A).rows() ); + const size_t N( (~A).columns() ); + + const bool remainder( !IsPadded::value || !IsPadded::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 // Storage order of the target dense matrix + friend inline EnableIf_< UseSMPAssign > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 a, b; + blaze::DynamicMatrix 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 + operator*( const DenseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecTDVecMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct Rows< DVecTDVecMultExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct Columns< DVecTDVecMultExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct IsAligned< DVecTDVecMultExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct IsPadded< DVecTDVecMultExpr > + : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool AF > +struct SubmatrixExprTrait< DVecTDVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct RowExprTrait< DVecTDVecMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< ReturnType_, VT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct ColumnExprTrait< DVecTDVecMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< VT1, ReturnType_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private VecTVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side sparse vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side sparse vector expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense vector expression. + typedef ElementType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef MultExprTrait_ 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::value || !IsNumeric::value || + IsComputation::value || !IsNumeric::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_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::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::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DVecTSVecMultExpr This; //!< Type of this DVecTSVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side sparse vector expression. + typedef If_< IsExpression, const VT2, const VT2& > RightOperand; + + //! Type for the assignment of the left-hand side dense vector operand. + typedef If_< IsComputation, const RT1, CT1 > LT; + + //! Type for the assignment of the right-hand side dense vector operand. + typedef If_< IsComputation, 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 Element; + + //! Element type of the dense vector expression + typedef ET1 LeftElement; + + //! Iterator type of the sparse vector expression. + typedef ConstIterator_< RemoveReference_ > 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::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 > + assign( DenseMatrix& 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_ > 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& 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 > + selectAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + typedef ConstIterator_< RemoveReference_ > 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 > + selectAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + const size_t M( (~A).rows() ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ y1( set( element->value() ) ); + + size_t i( 0UL ); + + for( ; iindex(), x.load(i) * y1 ); + } + for( ; remainder && iindex()) = 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 > + assign( SparseMatrix& 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_ > 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; iindex(), 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& 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_ > 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 > + addAssign( DenseMatrix& 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_ > 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& 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 > + selectAddAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + typedef ConstIterator_< RemoveReference_ > 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 > + selectAddAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + const size_t M( (~A).rows() ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ y1( set( element->value() ) ); + + size_t i( 0UL ); + + for( ; iindex(), (~A).load(i,element->index()) + x.load(i) * y1 ); + } + for( ; remainder && iindex()) += 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 > + subAssign( DenseMatrix& 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_ > 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& 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 > + selectSubAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + typedef ConstIterator_< RemoveReference_ > 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 > + selectSubAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + const size_t M( (~A).rows() ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ y1( set( element->value() ) ); + + size_t i( 0UL ); + + for( ; iindex(), (~A).load(i,element->index()) - x.load(i) * y1 ); + } + for( ; remainder && iindex()) -= 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 a; + blaze::CompressedVector b; + blaze::CompressedMatrix 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 + operator*( const DenseVector& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecTSVecMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct Rows< DVecTSVecMultExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct Columns< DVecTSVecMultExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool AF > +struct SubmatrixExprTrait< DVecTSVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct RowExprTrait< DVecTSVecMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< ReturnType_, VT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct ColumnExprTrait< DVecTSVecMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< VT1, ReturnType_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecTransExpr + , private If< IsComputation, Computation, EmptyType >::Type +{ + private: + //**Type definitions**************************************************************************** + typedef CompositeType_ 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::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 This; //!< Type of this DVecTransExpr instance. + typedef TransposeType_ ResultType; //!< Result type for expression template evaluations. + typedef ResultType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ 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, 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_ 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::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 > + assign( DenseVector& lhs, const DVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + assign( SparseVector& lhs, const DVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + SVecTransposer 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 > + addAssign( DenseVector& lhs, const DVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + subAssign( DenseVector& lhs, const DVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + multAssign( DenseVector& lhs, const DVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + divAssign( DenseVector& lhs, const DVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + smpAssign( DenseVector& lhs, const DVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + smpAssign( SparseVector& lhs, const DVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + SVecTransposer 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 > + smpAddAssign( DenseVector& lhs, const DVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + smpSubAssign( DenseVector& lhs, const DVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + smpMultAssign( DenseVector& lhs, const DVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + smpDivAssign( DenseVector& lhs, const DVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 a; + blaze::DynamicVector b; + // ... Resizing and initialization + b = trans( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const DVecTransExpr trans( const DenseVector& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return DVecTransExpr( ~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 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::Operand trans( const DVecTransExpr& dv ) +{ + BLAZE_FUNCTION_TRACE; + + return dv.operand(); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct Size< DVecTransExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct IsAligned< DVecTransExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct IsPadded< DVecTransExpr > + : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct DVecTransExprTrait< DVecTransExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector > + , Operand_< DVecTransExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TDVecTransExprTrait< DVecTransExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector > + , Operand_< DVecTransExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF, bool AF > +struct SubvectorExprTrait< DVecTransExpr, AF > +{ + public: + //********************************************************************************************** + using Type = TransExprTrait_< SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > +{ + public: + //**Type definitions**************************************************************************** + typedef DVecTransposer This; //!< Type of this DVecTransposer instance. + typedef TransposeType_ ResultType; //!< Result type for expression template evaluations. + typedef ResultType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the vector elements. + typedef SIMDTrait_ SIMDType; //!< SIMD type of the vector elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef Reference_ Reference; //!< Reference to a non-constant vector value. + typedef ConstReference_ ConstReference; //!< Reference to a constant vector value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant vector value. + typedef ConstPointer_ ConstPointer; //!< Pointer to a constant vector value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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, 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, 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& 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 // Type of the right-hand side sparse vector + inline void assign( const SparseVector& rhs ) + { + BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF ); + + BLAZE_INTERNAL_ASSERT( dv_.size() == (~rhs).size(), "Invalid vector sizes" ); + + typedef ConstIterator_ 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& 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 // Type of the right-hand side sparse vector + inline void addAssign( const SparseVector& rhs ) + { + BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF ); + + BLAZE_INTERNAL_ASSERT( dv_.size() == (~rhs).size(), "Invalid vector sizes" ); + + typedef ConstIterator_ 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& 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 // Type of the right-hand side sparse vector + inline void subAssign( const SparseVector& rhs ) + { + BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF ); + + BLAZE_INTERNAL_ASSERT( dv_.size() == (~rhs).size(), "Invalid vector sizes" ); + + typedef ConstIterator_ 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& 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 // Type of the right-hand side dense vector + inline void multAssign( const SparseVector& rhs ) + { + BLAZE_CONSTRAINT_MUST_BE_VECTOR_WITH_TRANSPOSE_FLAG( VT2, TF ); + + BLAZE_INTERNAL_ASSERT( dv_.size() == (~rhs).size(), "Invalid vector sizes" ); + + typedef ConstIterator_ 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& 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 // Transpose flag +inline void reset( DVecTransposer& v ) +{ + v.reset(); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct IsAligned< DVecTransposer > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct IsPadded< DVecTransposer > + : public BoolConstant< IsPadded::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTORTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct SubvectorTrait< DVecTransposer > +{ + using Type = SubvectorTrait_< ResultType_< DVecTransposer > >; +}; +/*! \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 + + +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 +{}; +//************************************************************************************************* + +} // 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 + + +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 +{}; +//************************************************************************************************* + +} // 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 + + +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 + + +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 + + +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 trans( const DenseVector& ); + +template< typename VT, bool TF > +inline const SVecTransExpr trans( const SparseVector& ); + +template< typename MT, bool SO > +inline const DMatTransExpr trans( const DenseMatrix& ); + +template< typename MT, bool SO > +inline const SMatTransExpr trans( const SparseMatrix& ); + +template< typename VT, bool TF > +inline const DVecSerialExpr serial( const DenseVector& ); + +template< typename VT, bool TF > +inline const SVecSerialExpr serial( const SparseVector& ); + +template< typename MT, bool SO > +inline const DMatSerialExpr serial( const DenseMatrix& ); + +template< typename MT, bool SO > +inline const SMatSerialExpr serial( const SparseMatrix& ); + +template< typename VT, bool TF, typename OP > +inline const DVecForEachExpr forEach( const DenseVector&, OP ); + +template< typename VT, bool TF, typename OP > +inline const SVecForEachExpr forEach( const SparseVector&, OP ); + +template< typename MT, bool SO, typename OP > +inline const DMatForEachExpr forEach( const DenseMatrix&, OP ); + +template< typename MT, bool SO, typename OP > +inline const SMatForEachExpr forEach( const SparseMatrix&, 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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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( 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( this ); + } + //********************************************************************************************** +}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Matrix global functions */ +//@{ +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE typename MT::Iterator begin( Matrix& matrix, size_t i ); + +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE typename MT::ConstIterator begin( const Matrix& matrix, size_t i ); + +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE typename MT::ConstIterator cbegin( const Matrix& matrix, size_t i ); + +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE typename MT::Iterator end( Matrix& matrix, size_t i ); + +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE typename MT::ConstIterator end( const Matrix& matrix, size_t i ); + +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE typename MT::ConstIterator cend( const Matrix& matrix, size_t i ); + +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE size_t rows( const Matrix& matrix ) noexcept; + +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE size_t columns( const Matrix& matrix ) noexcept; + +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE size_t capacity( const Matrix& matrix ) noexcept; + +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE size_t capacity( const Matrix& matrix, size_t i ) noexcept; + +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE size_t nonZeros( const Matrix& matrix ); + +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE size_t nonZeros( const Matrix& matrix, size_t i ); + +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE void resize( Matrix& matrix, size_t rows, size_t columns, bool preserve=true ); + +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE void transpose( Matrix& matrix ); + +template< typename MT, bool SO > +BLAZE_ALWAYS_INLINE bool isSquare( const Matrix& matrix ) noexcept; + +template< typename MT1, bool SO1, typename MT2, bool SO2 > +BLAZE_ALWAYS_INLINE bool isSame( const Matrix& a, const Matrix& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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 > + resize_backend( Matrix& 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, Not< IsSquare > > > + resize_backend( Matrix& 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, IsSquare > > + resize_backend( Matrix& 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 A( 3UL, 3UL ); + resize( A, 5UL, 2UL ); // OK: regular resize operation + + blaze::SymmetricMatrix< DynamicMatrix > 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 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& 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& 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& 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& matrix ) noexcept +{ + return ( IsSquare::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 MatrixType; + typedef blaze::Submatrix 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& a, const Matrix& b ) noexcept +{ + return ( IsSame::value && + reinterpret_cast( &a ) == reinterpret_cast( &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& lhs, const Matrix& 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 > + assign_backend( Matrix& lhs, const Matrix& 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 > + assign_backend( Matrix& lhs, const Matrix& 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& lhs, const Matrix& rhs ) +{ + BLAZE_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& lhs, const Matrix& 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 > + addAssign_backend( Matrix& lhs, const Matrix& 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 > + addAssign_backend( Matrix& lhs, const Matrix& 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& lhs, const Matrix& rhs ) +{ + BLAZE_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& lhs, const Matrix& 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 > + subAssign_backend( Matrix& lhs, const Matrix& 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 > + subAssign_backend( Matrix& lhs, const Matrix& 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& lhs, const Matrix& rhs ) +{ + BLAZE_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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Vector& 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& 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 + + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side sparse matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side dense matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::value && + T1::simdEnabled && T3::simdEnabled && + IsRowMajorMatrix::value && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::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::value && + !IsDiagonal::value && + !IsResizable< ElementType_ >::value && + !IsResizable::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::value && + !UseOptimizedKernel::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef SMatDMatMultExpr This; //!< Type of this SMatDMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side dense matrix expression. + typedef If_< IsExpression, 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::value && + MT2::simdEnabled && + HasSIMDAdd::value && + HasSIMDMult::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::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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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& 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 > + selectAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( Or< IsRowMajorMatrix, IsDiagonal >::value ? B.columns() : 64UL ); + + reset( C ); + + for( size_t jj=0UL; jjindex() ); + + if( IsDiagonal::value ) + { + C(i,i1) = element->value() * B(i1,i1); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( max( jj, ( IsStrictlyUpper::value ? i1+1UL : i1 ) ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( jtmp, ( IsStrictlyLower::value ? i1 : i1+1UL ) ) ) + :( jtmp ) ); + + if( IsTriangular::value && jbegin >= jend ) + continue; + + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; jvalue() * 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 > + selectAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsRowMajorMatrix::value ? B.columns() : 64UL ); + + reset( C ); + + for( size_t jj=0UL; jjindex() ); + 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::value ) + ?( max( jj, ( IsStrictlyUpper::value ? i1+1UL : i1 ) ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( jtmp, ( IsStrictlyLower::value ? i4 : i4+1UL ) ) ) + :( jtmp ) ); + + if( IsTriangular::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; jindex() ); + const ET1 v1( element->value() ); + + const size_t jbegin( ( IsUpper::value ) + ?( max( jj, ( IsStrictlyUpper::value ? i1+1UL : i1 ) ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( jtmp, ( IsStrictlyLower::value ? i1 : i1+1UL ) ) ) + :( jtmp ) ); + + if( IsTriangular::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 // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedKernel > + selectAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const bool remainder( !IsPadded::value || !IsPadded::value ); + + reset( C ); + + for( size_t i=0UL; iindex() ); + 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::value ) + ?( ( IsStrictlyUpper::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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( ; jindex() ); + const ET1 v1( element->value() ); + + const SIMDType xmm1( set( v1 ) ); + + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Storage order of the target sparse matrix + friend inline void assign( SparseMatrix& 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_ ); + + 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& 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 > + selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( Or< IsRowMajorMatrix, IsDiagonal >::value ? B.columns() : 64UL ); + + for( size_t jj=0UL; jjindex() ); + + if( IsDiagonal::value ) + { + C(i,i1) += element->value() * B(i1,i1); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( max( jj, ( IsStrictlyUpper::value ? i1+1UL : i1 ) ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( jtmp, ( IsStrictlyLower::value ? i1 : i1+1UL ) ) ) + :( jtmp ) ); + + if( IsTriangular::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; jvalue() * 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; jvalue() * 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 > + selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsRowMajorMatrix::value ? B.columns() : 64UL ); + + for( size_t jj=0UL; jjindex() ); + 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::value ) + ?( max( jj, ( IsStrictlyUpper::value ? i1+1UL : i1 ) ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( jtmp, ( IsStrictlyLower::value ? i4 : i4+1UL ) ) ) + :( jtmp ) ); + + if( IsTriangular::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; jindex() ); + const ET1 v1( element->value() ); + + const size_t jbegin( ( IsUpper::value ) + ?( max( jj, ( IsStrictlyUpper::value ? i1+1UL : i1 ) ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( jtmp, ( IsStrictlyLower::value ? i1 : i1+1UL ) ) ) + :( jtmp ) ); + + if( IsTriangular::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 // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedKernel > + selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const bool remainder( !IsPadded::value || !IsPadded::value ); + + for( size_t i=0UL; iindex() ); + 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::value ) + ?( ( IsStrictlyUpper::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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( ; jindex() ); + const ET1 v1( element->value() ); + + const SIMDType xmm1( set( v1 ) ); + + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Storage order of the target dense matrix + friend inline void subAssign( DenseMatrix& 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 > + selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( Or< IsRowMajorMatrix, IsDiagonal >::value ? B.columns() : 64UL ); + + for( size_t jj=0UL; jjindex() ); + + if( IsDiagonal::value ) + { + C(i,i1) -= element->value() * B(i1,i1); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( max( jj, ( IsStrictlyUpper::value ? i1+1UL : i1 ) ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( jtmp, ( IsStrictlyLower::value ? i1 : i1+1UL ) ) ) + :( jtmp ) ); + + if( IsTriangular::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; jvalue() * 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; jvalue() * 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 > + selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsRowMajorMatrix::value ? B.columns() : 64UL ); + + for( size_t jj=0UL; jjindex() ); + 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::value ) + ?( max( jj, ( IsStrictlyUpper::value ? i1+1UL : i1 ) ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( jtmp, ( IsStrictlyLower::value ? i4 : i4+1UL ) ) ) + :( jtmp ) ); + + if( IsTriangular::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; jindex() ); + const ET1 v1( element->value() ); + + const size_t jbegin( ( IsUpper::value ) + ?( max( jj, ( IsStrictlyUpper::value ? i1+1UL : i1 ) ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( jtmp, ( IsStrictlyLower::value ? i1 : i1+1UL ) ) ) + :( jtmp ) ); + + if( IsTriangular::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 // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedKernel > + selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const bool remainder( !IsPadded::value || !IsPadded::value ); + + for( size_t i=0UL; iindex() ); + 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::value ) + ?( ( IsStrictlyUpper::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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( ; jindex() ); + const ET1 v1( element->value() ); + + const SIMDType xmm1( set( v1 ) ); + + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Storage order of the target dense matrix + friend inline EnableIf_< IsEvaluationRequired > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A; + blaze::DynamicMatrix 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 + operator*( const SparseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return SMatDMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< SMatDMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< SMatDMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsAligned< SMatDMatMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< SMatDMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< SMatDMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< SMatDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< SMatDMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< SMatDMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< SMatDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct DMatDVecMultExprTrait< SMatDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseVector, IsColumnVector > + , SMatDVecMultExprTrait_< MT1, DMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct DMatSVecMultExprTrait< SMatDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsSparseVector, IsColumnVector > + , SMatDVecMultExprTrait_< MT1, DMatSVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecDMatMultExprTrait< VT, SMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , TDVecDMatMultExprTrait_< TDVecSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecDMatMultExprTrait< VT, SMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , TSVecDMatMultExprTrait_< TSVecSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< SMatDMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< SMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< SMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatMatSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse matrix expression. + typedef ReturnType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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 This; //!< Type of this SMatDMatSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::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& 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& 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_ ); + + 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& 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& 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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A; + blaze::DynamicMatrix 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 + operator-( const SparseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return SMatDMatSubExpr( ~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, T3 > + operator+( const SMatDMatSubExpr& lhs, const DenseMatrix& 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, T3 > + operator-( const SMatDMatSubExpr& lhs, const DenseMatrix& 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 > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct Columns< SMatDMatSubExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsSymmetric< SMatDMatSubExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsHermitian< SMatDMatSubExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsLower< SMatDMatSubExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUniLower< SMatDMatSubExpr > + : public BoolConstant< And< IsUniLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsStrictlyLower< SMatDMatSubExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUpper< SMatDMatSubExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsUniUpper< SMatDMatSubExpr > + : public BoolConstant< And< IsUniUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct IsStrictlyUpper< SMatDMatSubExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatAddExprTrait< SMatDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatSMatAddExprTrait_< DMatDMatSubExprTrait_, MT1 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatAddExprTrait< SMatDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , DMatSMatAddExprTrait_< TDMatDMatSubExprTrait_, MT1 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct TDMatDMatAddExprTrait< SMatDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatTSMatAddExprTrait_< DMatTDMatSubExprTrait_, MT1 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct TDMatTDMatAddExprTrait< SMatDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDMatTSMatAddExprTrait_< TDMatTDMatSubExprTrait_, MT1 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatSubExprTrait< SMatDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , SMatDMatSubExprTrait_< MT1, DMatDMatAddExprTrait_ > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatSubExprTrait< SMatDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , SMatDMatSubExprTrait_< MT1, DMatTDMatAddExprTrait_ > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct TDMatDMatSubExprTrait< SMatDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , TSMatDMatSubExprTrait_< MT1, TDMatDMatAddExprTrait_ > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct TDMatTDMatSubExprTrait< SMatDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TSMatTDMatSubExprTrait_< MT1, TDMatTDMatAddExprTrait_ > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO, bool AF > +struct SubmatrixExprTrait< SMatDMatSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct RowExprTrait< SMatDMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool SO > +struct ColumnExprTrait< SMatDMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ MRT; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ VRT; //!< Result type of the right-hand side dense vector expression. + typedef CompositeType_ MCT; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense vector expression. + enum : bool { evaluateVector = IsComputation::value || RequiresEvaluation::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 This; //!< Type of this SMatDVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT, const MT& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, 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 > + assign( DenseVector& 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 > + assign( SparseVector& 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_ ); + + 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 > + addAssign( DenseVector& 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 > + subAssign( DenseVector& 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 > + multAssign( DenseVector& 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_ ); + + 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 > + divAssign( DenseVector& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 A; + blaze::DynamicVector 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, SMatDVecMultExpr > + operator*( const SparseMatrix& mat, const DenseVector& vec ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~mat).columns() != (~vec).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" ); + } + + return SMatDVecMultExpr( ~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, MultExprTrait_ > + operator*( const SparseMatrix& mat, const DenseVector& 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 > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT > +struct IsAligned< SMatDVecMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, bool AF > +struct SubvectorExprTrait< SMatDVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatEvalExpr + , private Computation +{ + public: + //**Type definitions**************************************************************************** + typedef SMatEvalExpr This; //!< Type of this SMatEvalExpr instance. + typedef ResultType_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ 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, 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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 A, B; + // ... Resizing and initialization + B = eval( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatEvalExpr eval( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatEvalExpr( ~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 eval( const SMatEvalExpr& sm ) +{ + return sm; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct Rows< SMatEvalExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct Columns< SMatEvalExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsSymmetric< SMatEvalExpr > + : public BoolConstant< IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsHermitian< SMatEvalExpr > + : public BoolConstant< IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsLower< SMatEvalExpr > + : public BoolConstant< IsLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUniLower< SMatEvalExpr > + : public BoolConstant< IsUniLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsStrictlyLower< SMatEvalExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUpper< SMatEvalExpr > + : public BoolConstant< IsUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUniUpper< SMatEvalExpr > + : public BoolConstant< IsUniUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsStrictlyUpper< SMatEvalExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct SMatEvalExprTrait< SMatEvalExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix > + , SMatEvalExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TSMatEvalExprTrait< SMatEvalExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix > + , SMatEvalExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool AF > +struct SubmatrixExprTrait< SMatEvalExpr, AF > +{ + public: + //********************************************************************************************** + using Type = EvalExprTrait_< SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct RowExprTrait< SMatEvalExpr > +{ + public: + //********************************************************************************************** + using Type = EvalExprTrait_< RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct ColumnExprTrait< SMatEvalExpr > +{ + public: + //********************************************************************************************** + using Type = EvalExprTrait_< ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatForEachExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the sparse matrix expression. + typedef OppositeType_ OT; //!< Opposite type of the sparse matrix expression. + typedef ReturnType_ 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::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 This; //!< Type of this SMatForEachExpr instance. + typedef ForEachTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + + //! Return type for expression template evaluations. + typedef decltype( std::declval()( std::declval() ) ) 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, 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 Element; + + //! Iterator type of the sparse matrix expression. + typedef ConstIterator_< RemoveReference_ > 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 > + assign( DenseMatrix& 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_ ); + + 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 + , IsSame< UnderlyingNumeric, UnderlyingNumeric > > > + assign( SparseMatrix& 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_ Iterator; + + assign( ~lhs, rhs.sm_ ); + + const size_t m( rhs.rows() ); + + for( size_t i=0UL; ivalue() = 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 + , IsSame< UnderlyingNumeric, UnderlyingNumeric > > > + assign( SparseMatrix& 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_ Iterator; + + assign( ~lhs, rhs.sm_ ); + + const size_t n( rhs.columns() ); + + for( size_t j=0UL; jvalue() = 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 + , Not< IsSame< UnderlyingNumeric, UnderlyingNumeric > > > > + assign( SparseMatrix& 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_ ); + + 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 > + addAssign( DenseMatrix& 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_ ); + + 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 > + subAssign( DenseMatrix& 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_ ); + + 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 > + smpAssign( DenseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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_ ); + + 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 > + smpSubAssign( DenseMatrix& 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_ ); + + 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 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 forEach( const SparseMatrix& sm, OP op ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = abs( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr abs( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = floor( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr floor( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = ceil( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr ceil( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 > A, B; + // ... Resizing and initialization + B = conj( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr conj( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 > 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_ ctrans( const SparseMatrix& 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 A, B; + // ... Resizing and initialization + B = real( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr real( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = imag( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr imag( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 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 sqrt( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 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 invsqrt( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 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 cbrt( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 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 invcbrt( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 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,SO> pow( const SparseMatrix& sm, ET exp ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ET ); + + return SMatForEachExpr,SO>( ~sm, Pow( 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 A, B; + // ... Resizing and initialization + B = exp( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr exp( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 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 log( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 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 log10( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = sin( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr sin( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 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 asin( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = sinh( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr sinh( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = asinh( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr asinh( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = cos( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr cos( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 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 acos( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = cosh( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr cosh( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 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 acosh( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = tan( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr tan( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = atan( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr atan( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 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 tanh( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 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 atanh( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = erf( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr erf( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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 A, B; + // ... Resizing and initialization + B = erfc( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatForEachExpr erfc( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatForEachExpr( ~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& abs( const SMatForEachExpr& 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& floor( const SMatForEachExpr& 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& ceil( const SMatForEachExpr& 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 > 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::Operand conj( const SMatForEachExpr& 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 > 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 conj( const SMatTransExpr,!SO>& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatTransExpr( 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& real( const SMatForEachExpr& 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& imag( const SMatForEachExpr& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return sm; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO > +struct Rows< SMatForEachExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO > +struct Columns< SMatForEachExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, typename ET, bool SO > +struct IsSymmetric< SMatForEachExpr,SO> > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; + +template< typename MT, bool SO > +struct IsSymmetric< SMatForEachExpr > + : public BoolConstant< IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsBuiltin< ElementType_ >::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, typename ET, bool SO > +struct IsHermitian< SMatForEachExpr,SO> > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; + +template< typename MT, bool SO > +struct IsHermitian< SMatForEachExpr > + : public BoolConstant< IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO > +struct IsLower< SMatForEachExpr > + : public BoolConstant< IsLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ET, bool SO > +struct IsUniLower< SMatForEachExpr,SO> > + : public BoolConstant< IsUniLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO > +struct IsStrictlyLower< SMatForEachExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO > +struct IsUpper< SMatForEachExpr > + : public BoolConstant< IsUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ET, bool SO > +struct IsUniUpper< SMatForEachExpr,SO> > + : public BoolConstant< IsUniUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO > +struct IsStrictlyUpper< SMatForEachExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct SMatForEachExprTrait< SMatForEachExpr, Abs > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix > + , SMatForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TSMatForEachExprTrait< SMatForEachExpr, Abs > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix > + , SMatForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct SMatForEachExprTrait< SMatForEachExpr, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix > + , Operand_< SMatForEachExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TSMatForEachExprTrait< SMatForEachExpr, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix > + , Operand_< SMatForEachExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct SMatForEachExprTrait< SMatTransExpr< SMatForEachExpr, false >, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix > + , SMatTransExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TSMatForEachExprTrait< SMatTransExpr< SMatForEachExpr, true >, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix > + , SMatTransExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct SMatForEachExprTrait< SMatForEachExpr, Real > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix > + , SMatForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TSMatForEachExprTrait< SMatForEachExpr, Real > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix > + , SMatForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO, bool AF > +struct SubmatrixExprTrait< SMatForEachExpr, AF > +{ + public: + //********************************************************************************************** + using Type = ForEachExprTrait_< SubmatrixExprTrait_, OP >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO > +struct RowExprTrait< SMatForEachExpr > +{ + public: + //********************************************************************************************** + using Type = ForEachExprTrait_< RowExprTrait_, OP >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename OP, bool SO > +struct ColumnExprTrait< SMatForEachExpr > +{ + public: + //********************************************************************************************** + using Type = ForEachExprTrait_< ColumnExprTrait_, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatAddExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side sparse matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse matrix expression. + typedef ReturnType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef AddExprTrait_ 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::value && IsSymmetric::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 This; //!< Type of this SMatSMatAddExpr instance. + typedef AddTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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& 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_ > RightIterator; + + assign( ~lhs, rhs.lhs_ ); + + if( !IsResizable< ElementType_ >::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& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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 > + assign( SparseMatrix& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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 nonzeros( n, 0UL ); + for( size_t i=0UL; iindex() < 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; jindex() < 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 > + assign( SparseMatrix& 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& 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& 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 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 + operator+( const SparseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return SMatSMatAddExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< SMatSMatAddExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< SMatSMatAddExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< SMatSMatAddExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< SMatSMatAddExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< SMatSMatAddExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< SMatSMatAddExpr > + : public BoolConstant< Or< And< IsUniLower, IsStrictlyLower > + , And< IsUniLower, IsStrictlyLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< SMatSMatAddExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< SMatSMatAddExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< SMatSMatAddExpr > + : public BoolConstant< Or< And< IsUniUpper, IsStrictlyUpper > + , And< IsUniUpper, IsStrictlyUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< SMatSMatAddExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< SMatSMatAddExpr, AF > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< SMatSMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< SMatSMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side sparse matrix expression. + enum : bool { evaluateRight = RequiresEvaluation::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::value && + IsSymmetric::value && IsSymmetric::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::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef SMatSMatMultExpr This; //!< Type of this SMatSMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 > + assign( DenseMatrix& 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_ LeftIterator; + typedef ConstIterator_ RightIterator; + + for( size_t i=0UL; iindex() ) ); + for( RightIterator relem=B.begin( lelem->index() ); relem!=rend; ++relem ) + { + if( IsResizable< ElementType_ >::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& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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 values ( (~lhs).columns(), ElementType() ); + std::vector valid ( (~lhs).columns(), 0 ); + std::vector 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 // Type of the target sparse matrix + friend inline DisableIf_< CanExploitSymmetry > + assign( SparseMatrix& 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 > + assign( Matrix& 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 > + addAssign( DenseMatrix& 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_ LeftIterator; + typedef ConstIterator_ RightIterator; + + for( size_t i=0UL; iindex() ) ); + 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 > + addAssign( Matrix& 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 > + subAssign( DenseMatrix& 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_ LeftIterator; + typedef ConstIterator_ RightIterator; + + for( size_t i=0UL; iindex() ) ); + 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 > + subAssign( Matrix& 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 > + smpAssign( Matrix& 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 > + smpAssign( Matrix& 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 > + smpAddAssign( DenseMatrix& 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 > + smpAddAssign( Matrix& 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 > + smpSubAssign( DenseMatrix& 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 > + smpSubAssign( Matrix& 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 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 + operator*( const SparseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return SMatSMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< SMatSMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< SMatSMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< SMatSMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< SMatSMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< SMatSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< SMatSMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< SMatSMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< SMatSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct SMatDVecMultExprTrait< SMatSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseVector, IsColumnVector > + , SMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct SMatSVecMultExprTrait< SMatSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsSparseVector, IsColumnVector > + , SMatSVecMultExprTrait_< MT1, SMatSVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecSMatMultExprTrait< VT, SMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , TDVecSMatMultExprTrait_< TDVecSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecSMatMultExprTrait< VT, SMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , TSVecSMatMultExprTrait_< TSVecSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< SMatSMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< SMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< SMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ReturnType_ RN1; //!< ReturnType type of the left-hand side sparse matrix expression. + typedef ReturnType_ RN2; //!< ReturnType type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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::value && IsSymmetric::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 This; //!< Type of this SMatSMatSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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& 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_ > RightIterator; + + assign( ~lhs, rhs.lhs_ ); + + if( !IsResizable< ElementType_ >::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& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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 > + assign( SparseMatrix& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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 nonzeros( n, 0UL ); + for( size_t i=0UL; iindex() < 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; jindex() < 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 > + assign( SparseMatrix& 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& 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& 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 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 + operator-( const SparseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return SMatSMatSubExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< SMatSMatSubExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< SMatSMatSubExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< SMatSMatSubExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< SMatSMatSubExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< SMatSMatSubExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< SMatSMatSubExpr > + : public BoolConstant< And< IsUniLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< SMatSMatSubExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< SMatSMatSubExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< SMatSMatSubExpr > + : public BoolConstant< And< IsUniUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< SMatSMatSubExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< SMatSMatSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< SMatSMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< SMatSMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ MRT; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ VRT; //!< Result type of the right-hand side sparse vector expression. + typedef CompositeType_ MCT; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side sparse vector expression. + enum : bool { evaluateVector = RequiresEvaluation::value || IsComputation::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 This; //!< Type of this SMatSVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT, const MT& > LeftOperand; + + //! Composite type of the right-hand side sparse vector expression. + typedef If_< IsExpression, 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& 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_ > MatrixIterator; + typedef ConstIterator_< RemoveReference_ > VectorIterator; + + const VectorIterator vend( x.end() ); + + for( size_t i=0UL; iindex() < 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& lhs, const SMatSVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > MatrixIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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_ > MatrixIterator; + typedef ConstIterator_< RemoveReference_ > VectorIterator; + + const VectorIterator vend( x.end() ); + + for( size_t i=0UL; iindex() < 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& 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_ > MatrixIterator; + typedef ConstIterator_< RemoveReference_ > VectorIterator; + + const VectorIterator vend( x.end() ); + + for( size_t i=0UL; iindex() < 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& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 A; + blaze::CompressedVector 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, IsMatMatMultExpr >, SMatSVecMultExpr > + operator*( const SparseMatrix& mat, const SparseVector& vec ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~mat).columns() != (~vec).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" ); + } + + return SMatSVecMultExpr( ~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, MultExprTrait_ > + operator*( const SparseMatrix& mat, const SparseVector& 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, MultExprTrait_ > + operator*( const SparseMatrix& mat, const SparseVector& 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 > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, bool AF > +struct SubvectorExprTrait< SMatSVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatScalarDivExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the sparse matrix expression. + typedef ReturnType_ RN; //!< Return type of the sparse matrix expression. + typedef CompositeType_ 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::value }; + + //! Expression return type for the subscript operator. + typedef DivExprTrait_ 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::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 This; //!< Type of this SMatScalarDivExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, 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 Element; + + //! Iterator type of the sparse matrix expression. + typedef ConstIterator_< RemoveReference_ > 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 > + assign( DenseMatrix& 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 > + assign( SparseMatrix& 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 > + addAssign( DenseMatrix& lhs, const SMatScalarDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_ ); + + 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 > + subAssign( DenseMatrix& lhs, const SMatScalarDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_ ); + + 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 > + smpAddAssign( DenseMatrix& lhs, const SMatScalarDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_ ); + + 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 > + smpSubAssign( DenseMatrix& lhs, const SMatScalarDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_ ); + + 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 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, DivExprTrait_ > + operator/( const SparseMatrix& mat, T2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_USER_ASSERT( scalar != T2(0), "Division by zero detected" ); + + typedef DivExprTrait_ ReturnType; + typedef RightOperand_ ScalarType; + + if( IsMultExpr::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, Or< IsInvertible, IsInvertible > > + , MultExprTrait_< SMatScalarDivExpr, ST2 > > + operator*( const SMatScalarDivExpr& 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, Or< IsInvertible, IsInvertible > > + , MultExprTrait_< ST1, SMatScalarDivExpr > > + operator*( ST1 scalar, const SMatScalarDivExpr& 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 + , DivExprTrait_< MT, MultTrait_ > > + operator/( const SMatScalarDivExpr& mat, ST2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_USER_ASSERT( scalar != ST2(0), "Division by zero detected" ); + + typedef MultTrait_ MultType; + typedef DivExprTrait_ ReturnType; + typedef RightOperand_ ScalarType; + + if( IsMultExpr::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 > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct Columns< SMatScalarDivExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsSymmetric< SMatScalarDivExpr > + : public BoolConstant< IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsHermitian< SMatScalarDivExpr > + : public BoolConstant< IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsLower< SMatScalarDivExpr > + : public BoolConstant< IsLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsStrictlyLower< SMatScalarDivExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsUpper< SMatScalarDivExpr > + : public BoolConstant< IsUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsStrictlyUpper< SMatScalarDivExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SMATSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename ST2 > +struct SMatScalarMultExprTrait< SMatScalarDivExpr, ST2 > +{ + private: + //********************************************************************************************** + using ScalarType = DivTrait_; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , If_< IsInvertible + , SMatScalarMultExprTrait_ + , SMatScalarMultExpr< SMatScalarDivExpr, ST2, false > > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSMATSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename ST2 > +struct TSMatScalarMultExprTrait< SMatScalarDivExpr, ST2 > +{ + private: + //********************************************************************************************** + using ScalarType = DivTrait_; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , If_< IsInvertible + , SMatScalarMultExprTrait_ + , SMatScalarMultExpr< SMatScalarDivExpr, ST2, true > > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO, bool AF > +struct SubmatrixExprTrait< SMatScalarDivExpr, AF > +{ + public: + //********************************************************************************************** + using Type = DivExprTrait_< SubmatrixExprTrait_, ST >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct RowExprTrait< SMatScalarDivExpr > +{ + public: + //********************************************************************************************** + using Type = DivExprTrait_< RowExprTrait_, ST >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct ColumnExprTrait< SMatScalarDivExpr > +{ + public: + //********************************************************************************************** + using Type = DivExprTrait_< ColumnExprTrait_, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatScalarMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the sparse matrix expression. + typedef ReturnType_ RN; //!< Return type of the sparse matrix expression. + typedef CompositeType_ 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::value }; + + //! Expression return type for the subscript operator. + typedef MultExprTrait_ 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::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 This; //!< Type of this SMatScalarMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, 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 Element; + + //! Iterator type of the sparse matrix expression. + typedef ConstIterator_< RemoveReference_ > 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 > + assign( DenseMatrix& 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 > + assign( SparseMatrix& 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 > + addAssign( DenseMatrix& lhs, const SMatScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_ ); + + 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 > + subAssign( DenseMatrix& lhs, const SMatScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_ ); + + 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 > + smpAddAssign( DenseMatrix& lhs, const SMatScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_ ); + + 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 > + smpSubAssign( DenseMatrix& lhs, const SMatScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_SPARSE_MATRIX_TYPE( ResultType ); + BLAZE_CONSTRAINT_MUST_BE_REFERENCE_TYPE( CompositeType_ ); + + 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 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,SO> + operator-( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + typedef UnderlyingBuiltin_ ElementType; + return SMatScalarMultExpr( ~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 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, MultExprTrait_ > + operator*( const SparseMatrix& mat, T2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + return MultExprTrait_( ~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 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, MultExprTrait_ > + operator*( T1 scalar, const SparseMatrix& mat ) +{ + BLAZE_FUNCTION_TRACE; + + return MultExprTrait_( ~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 + operator-( const SMatScalarMultExpr& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatScalarMultExpr( 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 + , MultExprTrait_< SMatScalarMultExpr, ST2 > > + operator*( const SMatScalarMultExpr& 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 + , MultExprTrait_< ST1, SMatScalarMultExpr > > + operator*( ST1 scalar, const SMatScalarMultExpr& 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, Or< IsInvertible, IsInvertible > > + , DivExprTrait_< SMatScalarMultExpr, ST2 > > + operator/( const SMatScalarMultExpr& 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, VT > + operator*( const SMatScalarMultExpr& mat, const DenseVector& 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 > + operator*( const DenseVector& vec, const SMatScalarMultExpr& 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, DVecScalarMultExpr > + operator*( const SMatScalarMultExpr& mat, const DVecScalarMultExpr& 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, SMatScalarMultExpr > + operator*( const DVecScalarMultExpr& vec, const SMatScalarMultExpr& 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, VT > + operator*( const SMatScalarMultExpr& mat, const SparseVector& 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 > + operator*( const SparseVector& vec, const SMatScalarMultExpr& 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, SVecScalarMultExpr > + operator*( const SMatScalarMultExpr& mat, const SVecScalarMultExpr& 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, SMatScalarMultExpr > + operator*( const SVecScalarMultExpr& vec, const SMatScalarMultExpr& 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, MT2 > + operator*( const SMatScalarMultExpr& lhs, const DenseMatrix& 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 > + operator*( const DenseMatrix& lhs, const SMatScalarMultExpr& 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, MT2 > + operator*( const SMatScalarMultExpr& lhs, const SparseMatrix& 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 > + operator*( const SparseMatrix& lhs, const SMatScalarMultExpr& 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, SMatScalarMultExpr > + operator*( const SMatScalarMultExpr& lhs, const SMatScalarMultExpr& 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 > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct Columns< SMatScalarMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsSymmetric< SMatScalarMultExpr > + : public BoolConstant< IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsHermitian< SMatScalarMultExpr > + : public BoolConstant< IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsLower< SMatScalarMultExpr > + : public BoolConstant< IsLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsStrictlyLower< SMatScalarMultExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsUpper< SMatScalarMultExpr > + : public BoolConstant< IsUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct IsStrictlyUpper< SMatScalarMultExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SMATSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename ST2 > +struct SMatScalarMultExprTrait< SMatScalarMultExpr, ST2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , SMatScalarMultExprTrait_< MT, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSMATSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename ST2 > +struct TSMatScalarMultExprTrait< SMatScalarMultExpr, ST2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , TSMatScalarMultExprTrait_< MT, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SMATSCALARDIVEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename ST2 > +struct SMatScalarDivExprTrait< SMatScalarMultExpr, ST2 > +{ + private: + //********************************************************************************************** + using ScalarType = DivTrait_; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , If_< IsInvertible + , SMatScalarMultExprTrait_ + , SMatScalarDivExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSMATSCALARDIVEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename ST2 > +struct TSMatScalarDivExprTrait< SMatScalarMultExpr, ST2 > +{ + private: + //********************************************************************************************** + using ScalarType = DivTrait_; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , If_< IsInvertible + , TSMatScalarMultExprTrait_ + , TSMatScalarDivExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SMATDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, typename VT > +struct SMatDVecMultExprTrait< SMatScalarMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseVector, IsColumnVector + , IsNumeric > + , DVecScalarMultExprTrait_< SMatDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename VT, typename ST2 > +struct SMatDVecMultExprTrait< SMatScalarMultExpr, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseVector, IsColumnVector + , IsNumeric, IsNumeric > + , DVecScalarMultExprTrait_< SMatDVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSMATDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, typename VT > +struct TSMatDVecMultExprTrait< SMatScalarMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector + , IsNumeric > + , DVecScalarMultExprTrait_< TSMatDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename VT, typename ST2 > +struct TSMatDVecMultExprTrait< SMatScalarMultExpr, DVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector + , IsNumeric, IsNumeric > + , DVecScalarMultExprTrait_< TSMatDVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDVECSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, typename ST > +struct TDVecSMatMultExprTrait< VT, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric > + , TDVecScalarMultExprTrait_< TDVecSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename MT, typename ST2 > +struct TDVecSMatMultExprTrait< DVecScalarMultExpr, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , TDVecScalarMultExprTrait_< TDVecSMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDVECTSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, typename ST > +struct TDVecTSMatMultExprTrait< VT, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TDVecScalarMultExprTrait_< TDVecTSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename MT, typename ST2 > +struct TDVecTSMatMultExprTrait< DVecScalarMultExpr, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , TDVecScalarMultExprTrait_< TDVecTSMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SMATSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, typename VT > +struct SMatSVecMultExprTrait< SMatScalarMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsSparseVector, IsColumnVector + , IsNumeric > + , SVecScalarMultExprTrait_< SMatSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename VT, typename ST2 > +struct SMatSVecMultExprTrait< SMatScalarMultExpr, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsSparseVector, IsColumnVector + , IsNumeric, IsNumeric > + , SVecScalarMultExprTrait_< SMatSVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSMATSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, typename VT > +struct TSMatSVecMultExprTrait< SMatScalarMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector + , IsNumeric > + , SVecScalarMultExprTrait_< TSMatSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST1, typename VT, typename ST2 > +struct TSMatSVecMultExprTrait< SMatScalarMultExpr, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector + , IsNumeric, IsNumeric > + , SVecScalarMultExprTrait_< TSMatSVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSVECSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, typename ST > +struct TSVecSMatMultExprTrait< VT, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric > + , TSVecScalarMultExprTrait_< TSVecSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename MT, typename ST2 > +struct TSVecSMatMultExprTrait< SVecScalarMultExpr, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , TSVecScalarMultExprTrait_< TSVecSMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSVECTSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, typename ST > +struct TSVecTSMatMultExprTrait< VT, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TSVecScalarMultExprTrait_< TSVecTSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename MT, typename ST2 > +struct TSVecTSMatMultExprTrait< SVecScalarMultExpr, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , TSVecScalarMultExprTrait_< TSVecTSMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DMATSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename ST > +struct DMatSMatMultExprTrait< MT1, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric > + , DMatScalarMultExprTrait_< DMatSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DMATTSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename ST > +struct DMatTSMatMultExprTrait< MT1, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric > + , DMatScalarMultExprTrait_< DMatTSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDMATSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename ST > +struct TDMatSMatMultExprTrait< MT1, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric > + , TDMatScalarMultExprTrait_< TDMatSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDMATTSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename ST > +struct TDMatTSMatMultExprTrait< MT1, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TDMatScalarMultExprTrait_< TDMatTSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SMATDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct SMatDMatMultExprTrait< SMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric > + , DMatScalarMultExprTrait_< SMatDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SMATTDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct SMatTDMatMultExprTrait< SMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric > + , DMatScalarMultExprTrait_< SMatTDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSMATDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct TSMatDMatMultExprTrait< SMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric > + , TDMatScalarMultExprTrait_< TSMatDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSMATTDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct TSMatTDMatMultExprTrait< SMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TDMatScalarMultExprTrait_< TSMatTDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SMATSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct SMatSMatMultExprTrait< SMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric > + , SMatScalarMultExprTrait_< SMatSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename ST > +struct SMatSMatMultExprTrait< MT1, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric > + , SMatScalarMultExprTrait_< SMatSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct SMatSMatMultExprTrait< SMatScalarMultExpr, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , SMatScalarMultExprTrait_< SMatSMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SMATTSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct SMatTSMatMultExprTrait< SMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric > + , SMatScalarMultExprTrait_< SMatTSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename ST > +struct SMatTSMatMultExprTrait< MT1, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric > + , SMatScalarMultExprTrait_< SMatTSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct SMatTSMatMultExprTrait< SMatScalarMultExpr, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , SMatScalarMultExprTrait_< SMatTSMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSMATSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct TSMatSMatMultExprTrait< SMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric > + , TSMatScalarMultExprTrait_< TSMatSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename ST > +struct TSMatSMatMultExprTrait< MT1, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric > + , TSMatScalarMultExprTrait_< TSMatSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct TSMatSMatMultExprTrait< SMatScalarMultExpr, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric, IsNumeric > + , TSMatScalarMultExprTrait_< TSMatSMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSMATSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST, typename MT2 > +struct TSMatTSMatMultExprTrait< SMatScalarMultExpr, MT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TSMatScalarMultExprTrait_< TSMatTSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename ST > +struct TSMatTSMatMultExprTrait< MT1, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TSMatScalarMultExprTrait_< TSMatTSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename ST1, typename MT2, typename ST2 > +struct TSMatTSMatMultExprTrait< SMatScalarMultExpr, SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric, IsNumeric > + , TSMatScalarMultExprTrait_< TSMatTSMatMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO, bool AF > +struct SubmatrixExprTrait< SMatScalarMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_, ST >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct RowExprTrait< SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, ST >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename ST, bool SO > +struct ColumnExprTrait< SMatScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< ColumnExprTrait_, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatSerialExpr + , private Computation +{ + public: + //**Type definitions**************************************************************************** + typedef SMatSerialExpr This; //!< Type of this SMatSerialExpr instance. + typedef ResultType_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ 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, 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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 A, B; + // ... Resizing and initialization + B = serial( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatSerialExpr serial( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatSerialExpr( ~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 serial( const SMatSerialExpr& sm ) +{ + return sm; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct Rows< SMatSerialExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct Columns< SMatSerialExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsSymmetric< SMatSerialExpr > + : public BoolConstant< IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsHermitian< SMatSerialExpr > + : public BoolConstant< IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsLower< SMatSerialExpr > + : public BoolConstant< IsLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUniLower< SMatSerialExpr > + : public BoolConstant< IsUniLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsStrictlyLower< SMatSerialExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUpper< SMatSerialExpr > + : public BoolConstant< IsUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUniUpper< SMatSerialExpr > + : public BoolConstant< IsUniUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsStrictlyUpper< SMatSerialExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct SMatSerialExprTrait< SMatSerialExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix > + , SMatSerialExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TSMatSerialExprTrait< SMatSerialExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix > + , SMatSerialExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool AF > +struct SubmatrixExprTrait< SMatSerialExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SerialExprTrait_< SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct RowExprTrait< SMatSerialExpr > +{ + public: + //********************************************************************************************** + using Type = SerialExprTrait_< RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct ColumnExprTrait< SMatSerialExpr > +{ + public: + //********************************************************************************************** + using Type = SerialExprTrait_< ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::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::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::value && + !IsResizable< ElementType_ >::value && + !IsResizable::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef SMatTDMatMultExpr This; //!< Type of this SMatTDMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side dense matrix expression. + typedef If_< IsExpression, 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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 > + assign( DenseMatrix& 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 > + selectAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsColumnMajorMatrix::value ? A.rows() : 256UL ); + + for( size_t ii=0UL; ii::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j) : A.upperBound(i,j) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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 > + selectAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsColumnMajorMatrix::value ? A.rows() : 256UL ); + + reset( C ); + + for( size_t ii=0UL; ii::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j) : A.upperBound(i,j) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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 > + assign( SparseMatrix& 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_ ); + + 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 > + assign( Matrix& 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 > + addAssign( DenseMatrix& 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 > + selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsColumnMajorMatrix::value ? A.rows() : 256UL ); + + for( size_t ii=0UL; ii::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j) : A.upperBound(i,j) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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 > + selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsColumnMajorMatrix::value ? A.rows() : 256UL ); + + for( size_t ii=0UL; ii::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j) : A.upperBound(i,j) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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 > + addAssign( Matrix& 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 > + subAssign( DenseMatrix& 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 > + selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsColumnMajorMatrix::value ? A.rows() : 256UL ); + + for( size_t ii=0UL; ii::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j) : A.upperBound(i,j) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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 > + selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsColumnMajorMatrix::value ? A.rows() : 256UL ); + + for( size_t ii=0UL; ii::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j+4UL) : A.upperBound(i,j+4UL) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j+2UL) : A.upperBound(i,j+2UL) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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::value ) + ?( IsStrictlyUpper::value ? A.lowerBound(i,j) : A.upperBound(i,j) ) + :( A.end(i) ) ); + ConstIterator element( ( IsLower::value ) + ?( IsStrictlyLower::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; kindex() ); + 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 > + subAssign( Matrix& 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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAssign( Matrix& 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 > + smpAddAssign( DenseMatrix& 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 > + smpAddAssign( Matrix& 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 > + smpSubAssign( DenseMatrix& 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 > + smpSubAssign( Matrix& 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 A; + blaze::DynamicMatrix B; + blaze::DynamicMatrix 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 + operator*( const SparseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return SMatTDMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< SMatTDMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< SMatTDMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsAligned< SMatTDMatMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< SMatTDMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< SMatTDMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< SMatTDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< SMatTDMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< SMatTDMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< SMatTDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct DMatDVecMultExprTrait< SMatTDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector > + , SMatDVecMultExprTrait_< MT1, TDMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct DMatSVecMultExprTrait< SMatTDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector > + , SMatDVecMultExprTrait_< MT1, TDMatSVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecDMatMultExprTrait< VT, SMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDVecTDMatMultExprTrait_< TDVecSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecDMatMultExprTrait< VT, SMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TSVecTDMatMultExprTrait_< TSVecSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< SMatTDMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< SMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< SMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private MatMatSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse matrix expression. + typedef ReturnType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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 This; //!< Type of this SMatTDMatSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::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& 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& 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_ ); + + 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& 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& 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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A; + blaze::DynamicMatrix B; + blaze::DynamicMatrix 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 + operator-( const SparseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return SMatTDMatSubExpr( ~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, T3 > + operator+( const SMatTDMatSubExpr& lhs, const DenseMatrix& 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, T3 > + operator-( const SMatTDMatSubExpr& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return lhs.leftOperand() - ( lhs.rightOperand() + (~rhs) ); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< SMatTDMatSubExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< SMatTDMatSubExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< SMatTDMatSubExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< SMatTDMatSubExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< SMatTDMatSubExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< SMatTDMatSubExpr > + : public BoolConstant< And< IsUniLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< SMatTDMatSubExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< SMatTDMatSubExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< SMatTDMatSubExpr > + : public BoolConstant< And< IsUniUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< SMatTDMatSubExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatAddExprTrait< SMatTDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatSMatAddExprTrait_< DMatTDMatSubExprTrait_, MT1 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatAddExprTrait< SMatTDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDMatSMatAddExprTrait_< TDMatTDMatSubExprTrait_, MT1 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatSubExprTrait< SMatTDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , SMatDMatSubExprTrait_< MT1, TDMatDMatAddExprTrait_ > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatSubExprTrait< SMatTDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , SMatTDMatSubExprTrait_< MT1, TDMatTDMatAddExprTrait_ > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< SMatTDMatSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< SMatTDMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< SMatTDMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatAddExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ReturnType_ RN1; //!< Evaluation type of the left-hand side sparse matrix expression. + typedef ReturnType_ RN2; //!< Evaluation type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef AddExprTrait_ 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::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 This; //!< Type of this SMatTSMatAddExpr instance. + typedef AddTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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& 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_ > RightIterator; + + assign( ~lhs, rhs.lhs_ ); + + if( !IsResizable< ElementType_ >::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 > + assign( SparseMatrix& 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_ > LeftIterator; + typedef ConstIterator_< OppositeType_ > 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_ 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 > + assign( SparseMatrix& 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 > + assign( SparseMatrix& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > RightIterator; + + // Evaluation of the left-hand side sparse matrix operand + const OppositeType_ 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 > + assign( SparseMatrix& 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& 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& 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A, C; + blaze::CompressedMatrix 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 + operator+( const SparseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return SMatTSMatAddExpr( ~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 A, C; + blaze::CompressedMatrix 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 + operator+( const SparseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return SMatTSMatAddExpr( ~rhs, ~lhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< SMatTSMatAddExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< SMatTSMatAddExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< SMatTSMatAddExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< SMatTSMatAddExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< SMatTSMatAddExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< SMatTSMatAddExpr > + : public BoolConstant< Or< And< IsUniLower, IsStrictlyLower > + , And< IsUniLower, IsStrictlyLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< SMatTSMatAddExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< SMatTSMatAddExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< SMatTSMatAddExpr > + : public BoolConstant< Or< And< IsUniUpper, IsStrictlyUpper > + , And< IsUniUpper, IsStrictlyUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< SMatTSMatAddExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< SMatTSMatAddExpr, AF > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< SMatTSMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< SMatTSMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value && IsSymmetric::value ) || + ( IsColumnMajorMatrix::value && IsSymmetric::value ) }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef SMatTSMatMultExpr This; //!< Type of this SMatTSMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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 > + assign( Matrix& 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_ ); + + const OppositeType_ 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 > + assign( Matrix& 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 > + assign( Matrix& 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_ ); + + const OppositeType_ 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 > + assign( Matrix& 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 > + addAssign( DenseMatrix& 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_ ); + + const OppositeType_ 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 > + addAssign( Matrix& 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 > + addAssign( DenseMatrix& 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_ ); + + const OppositeType_ 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 > + addAssign( Matrix& 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 > + subAssign( DenseMatrix& 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_ ); + + const OppositeType_ 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 > + subAssign( Matrix& 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 > + subAssign( DenseMatrix& 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_ ); + + const OppositeType_ 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 > + subAssign( Matrix& 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 > + smpAssign( Matrix& 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_ ); + + const OppositeType_ 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 > + smpAssign( Matrix& 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 > + smpAssign( Matrix& 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_ ); + + const OppositeType_ 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 > + smpAssign( Matrix& 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 > + smpAddAssign( DenseMatrix& 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_ ); + + const OppositeType_ 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 > + smpAddAssign( DenseMatrix& 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_ ); + + const OppositeType_ 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 > + smpAddAssign( Matrix& 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 > + smpAddAssign( Matrix& 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 > + smpSubAssign( DenseMatrix& 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_ ); + + const OppositeType_ 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 > + smpSubAssign( DenseMatrix& 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_ ); + + const OppositeType_ 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 > + smpSubAssign( Matrix& 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 > + smpSubAssign( Matrix& 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 A, C; + blaze::CompressedMatrix 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 + operator*( const SparseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return SMatTSMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< SMatTSMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< SMatTSMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< SMatTSMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< SMatTSMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< SMatTSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< SMatTSMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< SMatTSMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< SMatTSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct SMatDVecMultExprTrait< SMatTSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector > + , SMatDVecMultExprTrait_< MT1, TSMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct SMatSVecMultExprTrait< SMatTSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector > + , SMatSVecMultExprTrait_< MT1, TSMatSVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecSMatMultExprTrait< VT, SMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , TDVecTSMatMultExprTrait_< TDVecSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecSMatMultExprTrait< VT, SMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , TDVecTSMatMultExprTrait_< TDVecSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< SMatTSMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< SMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< SMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse matrix expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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::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 This; //!< Type of this SMatTSMatSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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& 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_ > RightIterator; + + assign( ~lhs, rhs.lhs_ ); + + if( !IsResizable< ElementType_ >::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 > + assign( SparseMatrix& 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_ > LeftIterator; + typedef ConstIterator_< OppositeType_ > 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_ 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 > + assign( SparseMatrix& 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 > + assign( SparseMatrix& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > RightIterator; + + // Evaluation of the left-hand side sparse matrix operand + const OppositeType_ 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 > + assign( SparseMatrix& 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& 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& 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A, C; + blaze::CompressedMatrix 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 + operator-( const SparseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return SMatTSMatSubExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< SMatTSMatSubExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< SMatTSMatSubExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< SMatTSMatSubExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< SMatTSMatSubExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< SMatTSMatSubExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< SMatTSMatSubExpr > + : public BoolConstant< And< IsUniLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< SMatTSMatSubExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< SMatTSMatSubExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< SMatTSMatSubExpr > + : public BoolConstant< And< IsUniUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< SMatTSMatSubExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< SMatTSMatSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< SMatTSMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< SMatTSMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > + , private MatTransExpr + , private If< IsComputation, Computation, EmptyType >::Type +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the sparse matrix expression. + typedef CompositeType_ 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::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 This; //!< Type of this SMatTransExpr instance. + typedef TransposeType_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef ResultType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ 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, 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_ > IteratorType; + + typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category. + typedef typename std::iterator_traits::value_type ValueType; //!< Type of the underlying pointers. + typedef typename std::iterator_traits::pointer PointerType; //!< Pointer return type. + typedef typename std::iterator_traits::reference ReferenceType; //!< Reference return type. + typedef typename std::iterator_traits::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 > + assign( DenseMatrix& 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 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 > + assign( SparseMatrix& 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 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 > + addAssign( DenseMatrix& 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 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 > + subAssign( DenseMatrix& 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 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 > + smpAssign( DenseMatrix& 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 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 > + smpAssign( SparseMatrix& 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 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 > + smpAddAssign( DenseMatrix& 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 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 > + smpSubAssign( DenseMatrix& 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 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 A; + blaze::CompressedMatrix B; + // ... Resizing and initialization + B = trans( A ); + \endcode +*/ +template< typename MT // Type of the sparse matrix + , bool SO > // Storage order +inline const SMatTransExpr trans( const SparseMatrix& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return SMatTransExpr( ~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 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::Operand trans( const SMatTransExpr& sm ) +{ + BLAZE_FUNCTION_TRACE; + + return sm.operand(); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct Rows< SMatTransExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct Columns< SMatTransExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsSymmetric< SMatTransExpr > + : public BoolConstant< IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsHermitian< SMatTransExpr > + : public BoolConstant< IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsLower< SMatTransExpr > + : public BoolConstant< IsUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUniLower< SMatTransExpr > + : public BoolConstant< IsUniUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsStrictlyLower< SMatTransExpr > + : public BoolConstant< IsStrictlyUpper::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUpper< SMatTransExpr > + : public BoolConstant< IsLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsUniUpper< SMatTransExpr > + : public BoolConstant< IsUniLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsStrictlyUpper< SMatTransExpr > + : public BoolConstant< IsStrictlyLower::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct SMatTransExprTrait< SMatTransExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix > + , Operand_< SMatTransExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT > +struct TSMatTransExprTrait< SMatTransExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix > + , Operand_< SMatTransExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool AF > +struct SubmatrixExprTrait< SMatTransExpr, AF > +{ + public: + //********************************************************************************************** + using Type = TransExprTrait_< SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct RowExprTrait< SMatTransExpr > +{ + public: + //********************************************************************************************** + using Type = TransExprTrait_< ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct ColumnExprTrait< SMatTransExpr > +{ + public: + //********************************************************************************************** + using Type = TransExprTrait_< RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, SO > +{ + public: + //**Type definitions**************************************************************************** + typedef SMatTransposer This; //!< Type of this SMatTransposer instance. + typedef TransposeType_ ResultType; //!< Result type for expression template evaluations. + typedef MT OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef ResultType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef Reference_ Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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, 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, 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& 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_ RhsIterator; + + const size_t m( rows() ); + + for( size_t i=0UL; iindex(), 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& 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_ RhsIterator; + + const size_t m( rows() ); + const size_t n( columns() ); + + // Counting the number of elements per row + std::vector rowLengths( m, 0UL ); + for( size_t j=0UL; jindex()]; + } + + // Resizing the sparse matrix + for( size_t i=0UL; iindex(), 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 : public SparseMatrix< SMatTransposer, true > +{ + public: + //**Type definitions**************************************************************************** + typedef SMatTransposer This; //!< Type of this SMatTransposer instance. + typedef TransposeType_ ResultType; //!< Result type for expression template evaluations. + typedef MT OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef ResultType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef Reference_ Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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, 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, 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& 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_ RhsIterator; + + const size_t m( rows() ); + const size_t n( columns() ); + + // Counting the number of elements per row + std::vector columnLengths( n, 0UL ); + for( size_t i=0UL; iindex()]; + } + + // Resizing the sparse matrix + for( size_t j=0UL; jindex(), 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& 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_ RhsIterator; + + const size_t n( columns() ); + + for( size_t j=0UL; jindex(), 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& 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& m ) noexcept +{ + return m.isIntact(); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct SubmatrixTrait< SMatTransposer > +{ + using Type = SubmatrixTrait_< ResultType_< SMatTransposer > >; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private CrossExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse vector expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side dense vector expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side sparse vector expression. + typedef ElementType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_< MultExprTrait_, MultExprTrait_ > ExprReturnType; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef SVecDVecCrossExpr This; //!< Type of this SVecDVecCrossExpr instance. + typedef CrossTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, const VT2, const VT2& > RightOperand; + + //! Composite type of the left-hand side sparse vector expression. + typedef const StaticVector LT; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsComputation, const StaticVector, 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& 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& 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_ ); + + 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& 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& 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& 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& 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 a( 3UL ); + blaze::DynamicVector b( 3UL ); + blaze::StaticVector 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 + operator%( const SparseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != 3UL || (~rhs).size() != 3UL ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid vector size for cross product" ); + } + + return SVecDVecCrossExpr( ~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 a( 3UL ); + blaze::DynamicVector b( 3UL ); + blaze::StaticVector 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 + cross( const SparseVector& lhs, const DenseVector& rhs ) +{ + return lhs % rhs; +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct Size< SVecDVecCrossExpr > : 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecVecDivExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse vector expression. + typedef CompositeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef DivExprTrait_ 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::value || RequiresEvaluation::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 This; //!< Type of this SVecDVecDivExpr instance. + typedef DivTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, 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 Element; + + //! Iterator type of the sparse vector expression. + typedef ConstIterator_< RemoveReference_ > 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 > + assign( DenseVector& lhs, const SVecDVecDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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 > + assign( SparseVector& lhs, const SVecDVecDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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 > + addAssign( DenseVector& lhs, const SVecDVecDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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 > + subAssign( DenseVector& lhs, const SVecDVecDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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 > + multAssign( DenseVector& lhs, const SVecDVecDivExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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( ; ivalue() / y[index]; + ++i; + } + + for( ; i a, c; + blaze::DynamicVector 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 + operator/( const SparseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + return SVecDVecDivExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct Size< SVecDVecDivExpr > + : public Max< Size, Size > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< SVecDVecDivExpr, AF > +{ + public: + //********************************************************************************************** + using Type = DivExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse vector expression. + typedef CompositeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef MultExprTrait_ 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::value || RequiresEvaluation::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 This; //!< Type of this SVecDVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, 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 Element; + + //! Iterator type of the sparse vector expression. + typedef ConstIterator_< RemoveReference_ > 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 > + assign( DenseVector& lhs, const SVecDVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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 > + assign( SparseVector& lhs, const SVecDVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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 > + addAssign( DenseVector& lhs, const SVecDVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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 > + subAssign( DenseVector& lhs, const SVecDVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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 > + multAssign( DenseVector& lhs, const SVecDVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > 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( ; ivalue() * y[index]; + ++i; + } + + for( ; i a, c; + blaze::DynamicVector 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 + operator*( const SparseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + return SVecDVecMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct Size< SVecDVecMultExpr > + : public Max< Size, Size > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< SVecDVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecVecSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse vector expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side dense vector expression. + typedef TransposeType_ TT1; //!< Transpose type of the left-hand side sparse vector expression. + typedef TransposeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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 This; //!< Type of this SVecDVecSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, 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::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& 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& 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_ ); + + 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& 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& 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& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 a; + blaze::DynamicVector 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 + operator-( const SparseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + return SVecDVecSubExpr( ~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, T3 > + operator+( const SVecDVecSubExpr& lhs, const DenseVector& 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, T3 > + operator-( const SVecDVecSubExpr& lhs, const DenseVector& 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 > + : public Max< Size, Size > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename VT3 > +struct DVecDVecAddExprTrait< SVecDVecSubExpr, VT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseVector, IsColumnVector + , IsDenseVector, IsColumnVector + , IsDenseVector, IsColumnVector > + , DVecSVecAddExprTrait_< DVecDVecSubExprTrait_, VT1 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename VT3 > +struct TDVecTDVecAddExprTrait< SVecDVecSubExpr, VT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseVector, IsRowVector + , IsDenseVector, IsRowVector > + , TDVecTSVecAddExprTrait_< TDVecTDVecSubExprTrait_, VT1 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename VT3 > +struct DVecDVecSubExprTrait< SVecDVecSubExpr, VT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseVector, IsColumnVector + , IsDenseVector, IsColumnVector + , IsDenseVector, IsColumnVector > + , SVecDVecSubExprTrait_< VT1, DVecDVecAddExprTrait_ > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename VT3 > +struct TDVecTDVecSubExprTrait< SVecDVecSubExpr, VT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseVector, IsRowVector + , IsDenseVector, IsRowVector > + , TSVecTDVecSubExprTrait_< VT1, TDVecTDVecAddExprTrait_ > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< SVecDVecSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecEvalExpr + , private Computation +{ + public: + //**Type definitions**************************************************************************** + typedef SVecEvalExpr This; //!< Type of this SVecEvalExpr instance. + typedef ResultType_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ 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, 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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 a, b; + // ... Resizing and initialization + b = eval( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const SVecEvalExpr eval( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecEvalExpr( ~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 eval( const SVecEvalExpr& sv ) +{ + return sv; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct Size< SVecEvalExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct SVecEvalExprTrait< SVecEvalExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector > + , SVecEvalExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TSVecEvalExprTrait< SVecEvalExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector > + , SVecEvalExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF, bool AF > +struct SubvectorExprTrait< SVecEvalExpr, AF > +{ + public: + //********************************************************************************************** + using Type = EvalExprTrait_< SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecForEachExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the sparse vector expression. + typedef ReturnType_ 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::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 This; //!< Type of this SVecForEachExpr instance. + typedef ForEachTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + + //! Return type for expression template evaluations. + typedef decltype( std::declval()( std::declval() ) ) 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, 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 Element; + + //! Iterator type of the sparse vector expression. + typedef ConstIterator_< RemoveReference_ > 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 > + assign( DenseVector& 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_ ); + + 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 + , IsSame< UnderlyingNumeric, UnderlyingNumeric > > > + assign( SparseVector& lhs, const SVecForEachExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef Iterator_ 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 + , Not< IsSame< UnderlyingNumeric, UnderlyingNumeric > > > > + assign( SparseVector& 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_ ); + + 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 > + addAssign( DenseVector& 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_ ); + + 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 > + subAssign( DenseVector& 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_ ); + + 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 > + multAssign( DenseVector& 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_ ); + + 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 > + smpAssign( DenseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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_ ); + + 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 > + smpSubAssign( DenseVector& 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_ ); + + 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 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 forEach( const SparseVector& sv, OP op ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = abs( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr abs( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = floor( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr floor( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = ceil( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr ceil( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = conj( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr conj( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 > 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_ ctrans( const SparseVector& 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 a, b; + // ... Resizing and initialization + b = real( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr real( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = imag( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr imag( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 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 sqrt( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 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 invsqrt( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 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 cbrt( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 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 invcbrt( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 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,TF> pow( const SparseVector& sv, ET exp ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_BE_NUMERIC_TYPE( ET ); + + return SVecForEachExpr,TF>( ~sv, Pow( 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 a, b; + // ... Resizing and initialization + b = exp( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr exp( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 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 log( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 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 log10( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = sin( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr sin( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 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 asin( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = sinh( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr sinh( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = asinh( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr asinh( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = cos( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr cos( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 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 acos( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = cosh( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr cosh( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 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 acosh( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = tan( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr tan( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = atan( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr atan( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 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 tanh( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 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 atanh( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = erf( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr erf( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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 a, b; + // ... Resizing and initialization + b = erfc( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecForEachExpr erfc( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecForEachExpr( ~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& abs( const SVecForEachExpr& 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& floor( const SVecForEachExpr& 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& ceil( const SVecForEachExpr& 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 > 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::Operand conj( const SVecForEachExpr& 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 > 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 conj( const SVecTransExpr,!TF>& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecTransExpr( 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& real( const SVecForEachExpr& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return sv; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename OP, bool TF > +struct Size< SVecForEachExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct SVecForEachExprTrait< SVecForEachExpr, Abs > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector > + , SVecForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TSVecForEachExprTrait< SVecForEachExpr, Abs > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector > + , SVecForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct SVecForEachExprTrait< SVecForEachExpr, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector > + , Operand_< SVecForEachExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TSVecForEachExprTrait< SVecForEachExpr, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector > + , Operand_< SVecForEachExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct SVecForEachExprTrait< SVecTransExpr< SVecForEachExpr, false >, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector > + , SVecTransExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TSVecForEachExprTrait< SVecTransExpr< SVecForEachExpr, true >, Conj > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector > + , SVecTransExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct SVecForEachExprTrait< SVecForEachExpr, Real > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector > + , SVecForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TSVecForEachExprTrait< SVecForEachExpr, Real > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector > + , SVecForEachExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename OP, bool TF, bool AF > +struct SubvectorExprTrait< SVecForEachExpr, AF > +{ + public: + //********************************************************************************************** + using Type = ForEachExprTrait_< SubvectorExprTrait_, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecVecAddExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side sparse vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse vector expression. + typedef CompositeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef AddExprTrait_ 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 This; //!< Type of this SVecSVecAddExpr instance. + typedef AddTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side sparse vector expression. + typedef If_< IsExpression, 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_ > > + assign( DenseVector& lhs, const SVecSVecAddExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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_ > > + assign( DenseVector& lhs, const SVecSVecAddExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& lhs, const SVecSVecAddExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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& 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& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 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 + operator+( const SparseVector& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + return SVecSVecAddExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct Size< SVecSVecAddExpr > + : public Max< Size, Size > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< SVecSVecAddExpr, AF > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private CrossExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side sparse vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse vector expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side sparse vector expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side sparse vector expression. + typedef ElementType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_< MultExprTrait_, MultExprTrait_ > ExprReturnType; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef SVecSVecCrossExpr This; //!< Type of this SVecSVecCrossExpr instance. + typedef CrossTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side sparse vector expression. + typedef If_< IsExpression, const VT2, const VT2& > RightOperand; + + //! Composite type of the left-hand side sparse vector expression. + typedef const StaticVector LT; + + //! Composite type of the right-hand side sparse vector expression. + typedef const StaticVector 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& 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& 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_ ); + + 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& 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& 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& 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& 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 a( 3UL ), b( 3UL ); + blaze::StaticVector 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 + operator%( const SparseVector& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != 3UL || (~rhs).size() != 3UL ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid vector size for cross product" ); + } + + return SVecSVecCrossExpr( ~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 a( 3UL ), b( 3UL ); + blaze::StaticVector 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 + cross( const SparseVector& lhs, const SparseVector& rhs ) +{ + return lhs % rhs; +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct Size< SVecSVecCrossExpr > : 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side sparse vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse vector expression. + typedef CompositeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef MultExprTrait_ ExprReturnType; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef SVecSVecMultExpr This; //!< Type of this SVecSVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side sparse vector expression. + typedef If_< IsExpression, 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& lhs, const SVecSVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& lhs, const SVecSVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& lhs, const SVecSVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& lhs, const SVecSVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& lhs, const SVecSVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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( ; iindex(); ++i ) + reset( (~lhs)[i] ); + (~lhs)[l->index()] *= l->value() * r->value(); + ++r; + ++i; + } + } + + for( ; i // Type of the target sparse vector + friend inline void multAssign( SparseVector& lhs, const SVecSVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_ Iterator1; + typedef ConstIterator_< RemoveReference_ > Iterator2; + typedef ConstIterator_< RemoveReference_ > 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 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 + operator*( const SparseVector& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + return SVecSVecMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct Size< SVecSVecMultExpr > + : public Max< Size, Size > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< SVecSVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecVecSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side sparse vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse vector expression. + typedef CompositeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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 This; //!< Type of this SVecSVecSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side sparse vector expression. + typedef If_< IsExpression, 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_ > > + assign( DenseVector& lhs, const SVecSVecSubExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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_ > > + assign( DenseVector& lhs, const SVecSVecSubExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& lhs, const SVecSVecSubExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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& 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& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 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 + operator-( const SparseVector& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + return SVecSVecSubExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF > +struct Size< SVecSVecSubExpr > + : public Max< Size, Size > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< SVecSVecSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecScalarDivExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the sparse vector expression. + typedef ReturnType_ RN; //!< Return type of the sparse vector expression. + typedef CompositeType_ 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::value }; + + //! Expression return type for the subscript operator. + typedef DivExprTrait_ 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::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 This; //!< Type of this SVecScalarDivExpr instance. + typedef DivTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, 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 Element; + + //! Iterator type of the sparse vector expression. + typedef ConstIterator_< RemoveReference_ > 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 > + assign( DenseVector& 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 > + assign( SparseVector& 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 > + addAssign( DenseVector& 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_ ); + + 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 > + subAssign( DenseVector& 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_ ); + + 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 > + multAssign( DenseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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_ ); + + 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 > + smpSubAssign( DenseVector& 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_ ); + + 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 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, DivExprTrait_ > + operator/( const SparseVector& vec, T2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_USER_ASSERT( scalar != T2(0), "Division by zero detected" ); + + typedef DivExprTrait_ ReturnType; + typedef RightOperand_ ScalarType; + + if( IsMultExpr::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, Or< IsInvertible, IsInvertible > > + , MultExprTrait_< SVecScalarDivExpr, ST2 > > + operator*( const SVecScalarDivExpr& 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, Or< IsInvertible, IsInvertible > > + , MultExprTrait_< ST1, SVecScalarDivExpr > > + operator*( ST1 scalar, const SVecScalarDivExpr& 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 + , DivExprTrait_< VT, MultTrait_ > > + operator/( const SVecScalarDivExpr& vec, ST2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_USER_ASSERT( scalar != ST2(0), "Division by zero detected" ); + + typedef MultTrait_ MultType; + typedef DivExprTrait_ ReturnType; + typedef RightOperand_ ScalarType; + + if( IsMultExpr::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 > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SVECSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename ST2 > +struct SVecScalarMultExprTrait< SVecScalarDivExpr, ST2 > +{ + private: + //********************************************************************************************** + using ScalarType = DivTrait_; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector + , IsNumeric, IsNumeric > + , If_< IsInvertible + , SVecScalarMultExprTrait_ + , SVecScalarMultExpr< SVecScalarDivExpr, ST2, false > > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSVECSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename ST2 > +struct TSVecScalarMultExprTrait< SVecScalarDivExpr, ST2 > +{ + private: + //********************************************************************************************** + using ScalarType = DivTrait_; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsNumeric, IsNumeric > + , If_< IsInvertible + , SVecScalarMultExprTrait_ + , SVecScalarMultExpr< SVecScalarDivExpr, ST2, true > > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTOREXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST, bool TF, bool AF > +struct SubvectorExprTrait< SVecScalarDivExpr, AF > +{ + public: + //********************************************************************************************** + using Type = DivExprTrait_< SubvectorExprTrait_, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecScalarMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT; //!< Result type of the sparse vector expression. + typedef ReturnType_ RN; //!< Return type of the sparse vector expression. + typedef CompositeType_ 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::value }; + + //! Expression return type for the subscript operator. + typedef MultExprTrait_ 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::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 This; //!< Type of this SVecScalarMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, 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 Element; + + //! Iterator type of the sparse vector expression. + typedef ConstIterator_< RemoveReference_ > 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 > + assign( DenseVector& 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 > + assign( SparseVector& 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 > + addAssign( DenseVector& 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_ ); + + 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 > + subAssign( DenseVector& 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_ ); + + 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 > + multAssign( DenseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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_ ); + + 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 > + smpSubAssign( DenseVector& 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_ ); + + 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 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,TF> + operator-( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + typedef UnderlyingBuiltin_ ElementType; + return SVecScalarMultExpr( ~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 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, MultExprTrait_ > + operator*( const SparseVector& vec, T2 scalar ) +{ + BLAZE_FUNCTION_TRACE; + + return MultExprTrait_( ~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 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, MultExprTrait_ > + operator*( T1 scalar, const SparseVector& vec ) +{ + BLAZE_FUNCTION_TRACE; + + return MultExprTrait_( ~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 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,TF> + normalize( const SparseVector& vec ) +{ + typedef ElementType_ 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( ~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 + operator-( const SVecScalarMultExpr& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecScalarMultExpr( 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, MultExprTrait_< SVecScalarMultExpr, ST2 > > + operator*( const SVecScalarMultExpr& 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, MultExprTrait_< ST1, SVecScalarMultExpr > > + operator*( ST1 scalar, const SVecScalarMultExpr& 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, Or< IsInvertible, IsInvertible > > + , DivExprTrait_< SVecScalarMultExpr, ST2 > > + operator/( const SVecScalarMultExpr& 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, VT2 > + operator*( const SVecScalarMultExpr& lhs, const DenseVector& 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 > + operator*( const DenseVector& lhs, const SVecScalarMultExpr& 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, VT2 > + operator*( const SVecScalarMultExpr& lhs, const DenseVector& 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 > + operator*( const DenseVector& lhs, const SVecScalarMultExpr& 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, VT2 > + operator*( const SVecScalarMultExpr& lhs, const SparseVector& 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 > + operator*( const SparseVector& lhs, const SVecScalarMultExpr& 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, SVecScalarMultExpr > + operator*( const SVecScalarMultExpr& lhs, const SVecScalarMultExpr& 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, VT2 > + operator*( const SVecScalarMultExpr& lhs, const SparseVector& 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 > + operator*( const SparseVector& lhs, const SVecScalarMultExpr& 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, SVecScalarMultExpr > + operator*( const SVecScalarMultExpr& lhs, const SVecScalarMultExpr& 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 > + operator*( const DenseMatrix& mat, const SVecScalarMultExpr& 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, MT > + operator*( const SVecScalarMultExpr& vec, const DenseMatrix& 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 > + operator*( const SparseMatrix& mat, const SVecScalarMultExpr& 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, MT > + operator*( const SVecScalarMultExpr& vec, const SparseMatrix& 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 > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SVECSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename ST2 > +struct SVecScalarMultExprTrait< SVecScalarMultExpr, ST2 > +{ + public: + //********************************************************************************************** + typedef If_< And< IsSparseVector, IsColumnVector + , IsNumeric, IsNumeric > + , SVecScalarMultExprTrait_< VT, MultTrait_ > + , INVALID_TYPE > Type; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSVECSCALARMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename ST2 > +struct TSVecScalarMultExprTrait< SVecScalarMultExpr, ST2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsNumeric, IsNumeric > + , TSVecScalarMultExprTrait_< VT, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SVECSCALARDIVEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename ST2 > +struct SVecScalarDivExprTrait< SVecScalarMultExpr, ST2 > +{ + private: + //********************************************************************************************** + using ScalarType = DivTrait_; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector + , IsNumeric, IsNumeric > + , If_< IsInvertible + , SVecScalarMultExprTrait_ + , SVecScalarDivExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSVECSCALARDIVEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST1, typename ST2 > +struct TSVecScalarDivExprTrait< SVecScalarMultExpr, ST2 > +{ + private: + //********************************************************************************************** + using ScalarType = DivTrait_; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsNumeric, IsNumeric > + , If_< IsInvertible + , TSVecScalarMultExprTrait_ + , TSVecScalarDivExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DVECSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename ST > +struct DVecSVecMultExprTrait< VT1, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsSparseVector, IsColumnVector + , IsNumeric > + , SVecScalarMultExprTrait_< DVecSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DVECTSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename ST > +struct DVecTSVecMultExprTrait< VT1, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsColumnVector + , IsSparseVector, IsRowVector + , IsNumeric > + , SMatScalarMultExprTrait_< DVecTSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDVECTSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename ST > +struct TDVecTSVecMultExprTrait< VT1, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseVector, IsRowVector + , IsNumeric > + , TSVecScalarMultExprTrait_< TDVecTSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SVECDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST, typename VT2 > +struct SVecDVecMultExprTrait< SVecScalarMultExpr, VT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector + , IsDenseVector, IsColumnVector + , IsNumeric > + , SVecScalarMultExprTrait_< SVecDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SVECTDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST, typename VT2 > +struct SVecTDVecMultExprTrait< SVecScalarMultExpr, VT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector + , IsDenseVector, IsRowVector + , IsNumeric > + , TSMatScalarMultExprTrait_< SVecTDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSVECTDVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST, typename VT2 > +struct TSVecTDVecMultExprTrait< SVecScalarMultExpr, VT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseVector, IsRowVector + , IsNumeric > + , TSVecScalarMultExprTrait_< TSVecTDVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SVECSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST, typename VT2 > +struct SVecSVecMultExprTrait< SVecScalarMultExpr, VT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector + , IsSparseVector, IsColumnVector + , IsNumeric > + , SVecScalarMultExprTrait_< SVecSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename ST > +struct SVecSVecMultExprTrait< VT1, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector + , IsSparseVector, IsColumnVector + , IsNumeric > + , SVecScalarMultExprTrait_< SVecSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST1, typename VT2, typename ST2 > +struct SVecSVecMultExprTrait< SVecScalarMultExpr, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector + , IsSparseVector, IsColumnVector + , IsNumeric, IsNumeric > + , SVecScalarMultExprTrait_< SVecSVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SVECTSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST, typename VT2 > +struct SVecTSVecMultExprTrait< SVecScalarMultExpr, VT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector + , IsSparseVector, IsRowVector + , IsNumeric > + , SMatScalarMultExprTrait_< SVecTSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename ST > +struct SVecTSVecMultExprTrait< VT1, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector + , IsSparseVector, IsRowVector + , IsNumeric > + , SMatScalarMultExprTrait_< SVecTSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST1, typename VT2, typename ST2 > +struct SVecTSVecMultExprTrait< SVecScalarMultExpr, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector + , IsSparseVector, IsRowVector + , IsNumeric, IsNumeric > + , SMatScalarMultExprTrait_< SVecTSVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSVECTSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST, typename VT2 > +struct TSVecTSVecMultExprTrait< SVecScalarMultExpr, VT2 > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseVector, IsRowVector + , IsNumeric > + , TSVecScalarMultExprTrait_< TSVecTSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, typename ST > +struct TSVecTSVecMultExprTrait< VT1, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseVector, IsRowVector + , IsNumeric > + , TSVecScalarMultExprTrait_< TSVecTSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename ST1, typename VT2, typename ST2 > +struct TSVecTSVecMultExprTrait< SVecScalarMultExpr, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseVector, IsRowVector + , IsNumeric, IsNumeric > + , TSVecScalarMultExprTrait_< TSVecTSVecMultExprTrait_, MultTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DMATSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, typename ST > +struct DMatSVecMultExprTrait< MT, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsRowMajorMatrix + , IsSparseVector, IsColumnVector + , IsNumeric > + , DVecScalarMultExprTrait_< DMatSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TDMATSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, typename ST > +struct TDMatSVecMultExprTrait< MT, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector + , IsNumeric > + , DVecScalarMultExprTrait_< TDMatSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSVECDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST, typename MT > +struct TSVecDMatMultExprTrait< SVecScalarMultExpr, MT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix + , IsNumeric > + , TDVecScalarMultExprTrait_< TSVecDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSVECTDMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST, typename MT > +struct TSVecTDMatMultExprTrait< SVecScalarMultExpr, MT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TDVecScalarMultExprTrait_< TSVecTDMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SMATSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, typename ST > +struct SMatSVecMultExprTrait< MT, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsRowMajorMatrix + , IsSparseVector, IsColumnVector + , IsNumeric > + , SVecScalarMultExprTrait_< SMatSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSMATSVECMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, typename ST > +struct TSMatSVecMultExprTrait< MT, SVecScalarMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector + , IsNumeric > + , SVecScalarMultExprTrait_< TSMatSVecMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSVECSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST, typename MT > +struct TSVecSMatMultExprTrait< SVecScalarMultExpr, MT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix + , IsNumeric > + , TSVecScalarMultExprTrait_< TSVecSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// TSVECTSMATMULTEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST, typename MT > +struct TSVecTSMatMultExprTrait< SVecScalarMultExpr, MT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix + , IsNumeric > + , TSVecScalarMultExprTrait_< TSVecTSMatMultExprTrait_, ST > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTOREXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename ST, bool TF, bool AF > +struct SubvectorExprTrait< SVecScalarMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecSerialExpr + , private Computation +{ + public: + //**Type definitions**************************************************************************** + typedef SVecSerialExpr This; //!< Type of this SVecSerialExpr instance. + typedef ResultType_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ 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, 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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 a, b; + // ... Resizing and initialization + b = serial( a ); + \endcode +*/ +template< typename VT // Type of the dense vector + , bool TF > // Transpose flag +inline const SVecSerialExpr serial( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecSerialExpr( ~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 serial( const SVecSerialExpr& sv ) +{ + return sv; +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct Size< SVecSerialExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct SVecSerialExprTrait< SVecSerialExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector > + , SVecSerialExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TSVecSerialExprTrait< SVecSerialExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector > + , SVecSerialExpr + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF, bool AF > +struct SubvectorExprTrait< SVecSerialExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SerialExprTrait_< SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private VecTVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side dense vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse vector expression. + typedef CompositeType_ CT2; //!< Composite type of the right-hand side dense vector expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side sparse vector expression. + typedef ElementType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef MultExprTrait_ 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::value || !IsNumeric::value || + IsComputation::value || !IsNumeric::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_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::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::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef SVecTDVecMultExpr This; //!< Type of this SVecTDVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, const VT2, const VT2& > RightOperand; + + //! Type for the assignment of the left-hand side dense vector operand. + typedef If_< IsComputation, const RT1, CT1 > LT; + + //! Type for the assignment of the right-hand side dense vector operand. + typedef If_< IsComputation, 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 Element; + + //! Iterator type of the sparse vector expression. + typedef ConstIterator_< RemoveReference_ > 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::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& 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 > + selectAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + const ConstIterator end( x.end() ); + + for( ConstIterator element=x.begin(); element!=end; ++element ) { + if( !isDefault( element->value() ) ) { + for( size_t j=0UL; jindex(),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 > + selectAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + const size_t N( (~A).columns() ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ x1( set( element->value() ) ); + + size_t j( 0UL ); + + for( ; jindex(), j, x1 * y.load(j) ); + } + for( ; remainder && jindex(),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 > + assign( DenseMatrix& 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_ > 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; iindex(),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& 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_ > 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; iindex(), 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 > + assign( SparseMatrix& 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_ > 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; iindex(), 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& 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 > + selectAddAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + const ConstIterator end( x.end() ); + + for( ConstIterator element=x.begin(); element!=end; ++element ) { + if( !isDefault( element->value() ) ) { + for( size_t i=0UL; iindex(),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 > + selectAddAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + const size_t N( (~A).columns() ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ x1( set( element->value() ) ); + + size_t j( 0UL ); + + for( ; jindex(), j, (~A).load(element->index(),j) + x1 * y.load(j) ); + } + for( ; remainder && jindex(),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 > + addAssign( DenseMatrix& 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_ > 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; iindex(),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& 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 > + selectSubAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + const ConstIterator end( x.end() ); + + for( ConstIterator element=x.begin(); element!=end; ++element ) { + if( !isDefault( element->value() ) ) { + for( size_t i=0UL; iindex(),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 > + selectSubAssignKernel( DenseMatrix& A, const VT3& x, const VT4& y ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + const size_t N( (~A).columns() ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ x1( set( element->value() ) ); + + size_t j( 0UL ); + + for( ; jindex(), j, (~A).load(element->index(),j) - x1 * y.load(j) ); + } + for( ; remainder && jindex(),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 > + subAssign( DenseMatrix& 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_ > 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; iindex(),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 a; + blaze::DynamicVector b; + blaze::CompressedMatrix 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 + operator*( const SparseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecTDVecMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct Rows< SVecTDVecMultExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct Columns< SVecTDVecMultExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool AF > +struct SubmatrixExprTrait< SVecTDVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct RowExprTrait< SVecTDVecMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< ReturnType_, VT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct ColumnExprTrait< SVecTDVecMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< VT1, ReturnType_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private VecTVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse vector expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse vector expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse vector expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side sparse vector expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse vector expression. + typedef CompositeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef MultExprTrait_ ExprReturnType; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef SVecTSVecMultExpr This; //!< Type of this SVecTSVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT1, const VT1& > LeftOperand; + + //! Composite type of the right-hand side sparse vector expression. + typedef If_< IsExpression, const VT2, const VT2& > RightOperand; + + //! Type for the assignment of the left-hand side dense vector operand. + typedef If_< IsComputation, const RT1, CT1 > LT; + + //! Type for the assignment of the right-hand side dense vector operand. + typedef If_< IsComputation, 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& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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 a, b; + blaze::CompressedMatrix 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 + operator*( const SparseVector& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecTSVecMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct Rows< SVecTSVecMultExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct Columns< SVecTSVecMultExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool AF > +struct SubmatrixExprTrait< SVecTSVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct RowExprTrait< SVecTSVecMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< ReturnType_, VT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2 > +struct ColumnExprTrait< SVecTSVecMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< VT1, ReturnType_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > + , private VecTransExpr + , private If< IsComputation, Computation, EmptyType >::Type +{ + private: + //**Type definitions**************************************************************************** + typedef CompositeType_ 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::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 This; //!< Type of this SVecTransExpr instance. + typedef TransposeType_ ResultType; //!< Result type for expression template evaluations. + typedef ResultType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ 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, 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_ > IteratorType; + + typedef std::forward_iterator_tag IteratorCategory; //!< The iterator category. + typedef typename std::iterator_traits::value_type ValueType; //!< Type of the underlying pointers. + typedef typename std::iterator_traits::pointer PointerType; //!< Pointer return type. + typedef typename std::iterator_traits::reference ReferenceType; //!< Reference return type. + typedef typename std::iterator_traits::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 > + assign( DenseVector& lhs, const SVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + assign( SparseVector& lhs, const SVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + SVecTransposer 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 > + addAssign( DenseVector& lhs, const SVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + subAssign( DenseVector& lhs, const SVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + multAssign( DenseVector& lhs, const SVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + smpAssign( DenseVector& lhs, const SVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + smpAssign( SparseVector& lhs, const SVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + SVecTransposer 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 > + smpAddAssign( DenseVector& lhs, const SVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + smpSubAssign( DenseVector& lhs, const SVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 > + smpMultAssign( DenseVector& lhs, const SVecTransExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + DVecTransposer 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 a; + blaze::CompressedVector b; + // ... Resizing and initialization + b = trans( a ); + \endcode +*/ +template< typename VT // Type of the sparse vector + , bool TF > // Transpose flag +inline const SVecTransExpr trans( const SparseVector& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return SVecTransExpr( ~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 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::Operand trans( const SVecTransExpr& sv ) +{ + BLAZE_FUNCTION_TRACE; + + return sv.operand(); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct Size< SVecTransExpr > : public Size +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct SVecTransExprTrait< SVecTransExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector > + , Operand_< SVecTransExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT > +struct TSVecTransExprTrait< SVecTransExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsColumnVector > + , Operand_< SVecTransExpr > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF, bool AF > +struct SubvectorExprTrait< SVecTransExpr, AF > +{ + public: + //********************************************************************************************** + using Type = TransExprTrait_< SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, TF > +{ + public: + //**Type definitions**************************************************************************** + typedef SVecTransposer This; //!< Type of this SVecTransposer instance. + typedef TransposeType_ ResultType; //!< Result type for expression template evaluations. + typedef ResultType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef const This& CompositeType; //!< Data type for composite expression templates. + typedef Reference_ Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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, 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, 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& 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 // Type of the right-hand side sparse vector + inline void assign( const SparseVector& 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_ 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& v ) +{ + v.reset(); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTORTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct SubvectorTrait< SVecTransposer > +{ + using Type = SubvectorTrait_< ResultType_< SVecTransposer > >; +}; +/*! \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 + + +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 + + +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 +{}; +//************************************************************************************************* + +} // 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 + + +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 +{}; +//************************************************************************************************* + +} // 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 + + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side dense matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::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::value && IsDiagonal::value ) && + !( IsDiagonal::value && IsColumnMajorMatrix::value ) && + !( IsDiagonal::value && IsRowMajorMatrix::value ) && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef TDMatDMatMultExpr This; //!< Type of this TDMatDMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side dense matrix expression. + typedef If_< IsExpression, 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::value && IsDiagonal::value ) && + MT1::simdEnabled && MT2::simdEnabled && + HasSIMDAdd::value && + HasSIMDMult::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::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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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& 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::value && IsDiagonal::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 >, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + if( IsStrictlyTriangular::value && kbegin == kend ) { + for( size_t j=0UL; j::value ) + ?( IsStrictlyUpper::value ? kbegin+1UL : kbegin ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? kbegin : kbegin+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + if( IsUpper::value && IsUpper::value ) { + for( size_t j=0UL; j::value ) { + reset( (~C)(i,0UL) ); + } + for( size_t j=jbegin; j::value && IsLower::value ) { + for( size_t j=jend; j::value ) { + reset( (~C)(i,N-1UL) ); + } + } + + for( size_t k=kbegin+1UL; k::value ) + ?( IsStrictlyUpper::value ? k+1UL : k ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? k-1UL : k ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j::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 >, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + if( IsStrictlyTriangular::value && kbegin == kend ) { + for( size_t i=0UL; i::value ) + ?( IsStrictlyLower::value ? kbegin+1UL : kbegin ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? kbegin : kbegin+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + if( IsLower::value && IsLower::value ) { + for( size_t i=0UL; i::value ) { + reset( (~C)(0UL,j) ); + } + for( size_t i=ibegin; i::value && IsUpper::value ) { + for( size_t i=iend; i::value ) { + reset( (~C)(M-1UL,j) ); + } + } + + for( size_t k=kbegin+1UL; k::value ) + ?( IsStrictlyLower::value ? k+1UL : k ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? k-1UL : k ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i::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 >, IsDiagonal > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jpos( ( IsLower::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), jend ) ) + :( jend ) ); + + if( IsUpper::value ) { + for( size_t j=jj; j::value ) { + for( size_t j=jpos; j // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + if( IsLower::value ) { + for( size_t i=0UL; i::value ) { + for( size_t i=iend; i // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + if( IsUpper::value ) { + for( size_t j=0UL; j::value ) { + for( size_t j=jend; j // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t ipos( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::value ? j : j+1UL ), iend ) ) + :( iend ) ); + + if( IsLower::value ) { + for( size_t i=ii; i::value ) { + for( size_t i=ipos; i // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + reset( C ); + + for( size_t i=0UL; i // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyUpper::value ? j : j+1UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + for( size_t jj=0UL; jj::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+4UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectLargeAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + for( size_t ii=0UL; ii::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i ,j) ); + SIMDType xmm2( (~C).load(i1,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+1UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( C, B ); + trmm( C, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(1) ); + } + else if( IsTriangular::value ) { + assign( C, A ); + trmm( C, B, CblasRight, ( IsLower::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& 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_ ); + + 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& 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::value && IsDiagonal::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 >, Not< IsDiagonal > > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + for( size_t k=kbegin; k::value ) + ?( IsStrictlyUpper::value ? k+1UL : k ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, Not< IsDiagonal > > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + for( size_t k=kbegin; k::value ) + ?( IsStrictlyLower::value ? k+1UL : k ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jpos( ( IsLower::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), jend ) ) + :( jend ) ); + + for( size_t j=jbegin; j // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t ipos( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::value ? j : j+1UL ), iend ) ) + :( iend ) ); + + for( size_t i=ibegin; i // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + for( size_t i=0UL; i // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAddAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + ElementType value1( (~C)(i ,j) ); + ElementType value2( (~C)(i+1UL,j) );; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallAddAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyUpper::value ? j : j+1UL ) ) + :( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + ElementType value1( (~C)(i,j ) ); + ElementType value2( (~C)(i,j+1UL) ); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeAddAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + for( size_t jj=0UL; jj::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+4UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectLargeAddAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + for( size_t ii=0UL; ii::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i ,j) ); + SIMDType xmm2( (~C).load(i1,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+1UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(1) ); + addAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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& 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::value && IsDiagonal::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 >, Not< IsDiagonal > > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + for( size_t k=kbegin; k::value ) + ?( IsStrictlyUpper::value ? k+1UL : k ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, Not< IsDiagonal > > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + for( size_t k=kbegin; k::value ) + ?( IsStrictlyLower::value ? k+1UL : k ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jpos( ( IsLower::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), jend ) ) + :( jend ) ); + + for( size_t j=jbegin; j // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t ipos( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::value ? j : j+1UL ), iend ) ) + :( iend ) ); + + for( size_t i=ibegin; i // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + for( size_t i=0UL; i // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallSubAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + ElementType value1( (~C)(i ,j) ); + ElementType value2( (~C)(i+1UL,j) ); + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallSubAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyUpper::value ? j : j+1UL ) ) + :( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + ElementType value1( (~C)(i,j ) ); + ElementType value2( (~C)(i,j+1UL) ); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeSubAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + for( size_t jj=0UL; jj::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+4UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedDefaultKernel > + selectLargeSubAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + for( size_t ii=0UL; ii::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i ,j) ); + SIMDType xmm2( (~C).load(i1,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+1UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(1) ); + subAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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, ST, true > + : public DenseMatrix< DMatScalarMultExpr< TDMatDMatMultExpr, ST, true >, true > + , private MatScalarMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef TDMatDMatMultExpr MMM; //!< Type of the dense matrix multiplication expression. + typedef ResultType_ RES; //!< Result type of the dense matrix multiplication expression. + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side dense matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + !( IsBuiltin< ElementType_ >::value && IsComplex::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::value && IsDiagonal::value ) && + !( IsDiagonal::value && IsColumnMajorMatrix::value ) && + !( IsDiagonal::value && IsRowMajorMatrix::value ) && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ + , T4 >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DMatScalarMultExpr This; //!< Type of this DMatScalarMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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 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::value && IsDiagonal::value ) && + MT1::simdEnabled && MT2::simdEnabled && + AreSIMDCombinable::value && + HasSIMDAdd::value && + HasSIMDMult::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::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_ 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& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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::value && IsDiagonal::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 >, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + if( IsStrictlyTriangular::value && kbegin == kend ) { + for( size_t j=0UL; j::value ) + ?( IsStrictlyUpper::value ? kbegin+1UL : kbegin ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? kbegin : kbegin+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + if( IsUpper::value && IsUpper::value ) { + for( size_t j=0UL; j::value ) { + reset( (~C)(i,0UL) ); + } + for( size_t j=jbegin; j::value && IsLower::value ) { + for( size_t j=jend; j::value ) { + reset( (~C)(i,N-1UL) ); + } + } + + for( size_t k=kbegin+1UL; k::value ) + ?( IsStrictlyUpper::value ? k+1UL : k ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? k-1UL : k ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j::value ) { + (~C)(i,jend) = A(i,k) * B(k,jend); + } + } + + { + const size_t jbegin( ( IsUpper::value && IsUpper::value ) + ?( IsStrictlyUpper::value || IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value && IsLower::value ) + ?( IsStrictlyLower::value || IsStrictlyLower::value ? i : i+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j // Type of the scalar value + static inline EnableIf_< And< Not< IsDiagonal >, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + if( IsStrictlyTriangular::value && kbegin == kend ) { + for( size_t i=0UL; i::value ) + ?( IsStrictlyLower::value ? kbegin+1UL : kbegin ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? kbegin : kbegin+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + if( IsLower::value && IsLower::value ) { + for( size_t i=0UL; i::value ) { + reset( (~C)(0UL,j) ); + } + for( size_t i=ibegin; i::value && IsUpper::value ) { + for( size_t i=iend; i::value ) { + reset( (~C)(M-1UL,j) ); + } + } + + for( size_t k=kbegin+1UL; k::value ) + ?( IsStrictlyLower::value ? k+1UL : k ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? k-1UL : k ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i::value ) { + (~C)(iend,j) = A(iend,k) * B(k,j); + } + } + + { + const size_t ibegin( ( IsLower::value && IsLower::value ) + ?( IsStrictlyLower::value || IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value && IsUpper::value ) + ?( IsStrictlyUpper::value || IsStrictlyUpper::value ? j : j+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i // Type of the scalar value + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jpos( ( IsLower::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), jend ) ) + :( jend ) ); + + if( IsUpper::value ) { + for( size_t j=jj; j::value ) { + for( size_t j=jpos; j // Type of the scalar value + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + if( IsLower::value ) { + for( size_t i=0UL; i::value ) { + for( size_t i=iend; i // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + if( IsUpper::value ) { + for( size_t j=0UL; j::value ) { + for( size_t j=jend; j // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t ipos( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::value ? j : j+1UL ), iend ) ) + :( iend ) ); + + if( IsLower::value ) { + for( size_t i=ii; i::value ) { + for( size_t i=ipos; i // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + reset( C ); + + for( size_t i=0UL; i // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyUpper::value ? j : j+1UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + const SIMDType factor( set( scalar ) ); + + for( size_t jj=0UL; jj::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+4UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectLargeAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + const SIMDType factor( set( scalar ) ); + + for( size_t ii=0UL; ii::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+2UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+4UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+2UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+1UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( C, B ); + trmm( C, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(scalar) ); + } + else if( IsTriangular::value ) { + assign( C, A ); + trmm( C, B, CblasRight, ( IsLower::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& 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_ ); + + 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& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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::value && IsDiagonal::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 >, Not< IsDiagonal > > > + 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 >, IsDiagonal > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jpos( ( IsLower::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), jend ) ) + :( jend ) ); + + for( size_t j=jbegin; j // Type of the scalar value + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultAddAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t ipos( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::value ? j : j+1UL ), iend ) ) + :( iend ) ); + + for( size_t i=ibegin; i // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + for( size_t i=0UL; i // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAddAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallAddAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyUpper::value ? j : j+1UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeAddAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + const SIMDType factor( set( scalar ) ); + + for( size_t jj=0UL; jj::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+4UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectLargeAddAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + const SIMDType factor( set( scalar ) ); + + for( size_t ii=0UL; ii::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+2UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+4UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+2UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+1UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(scalar) ); + addAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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::value && IsDiagonal::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 >, Not< IsDiagonal > > > + 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 >, IsDiagonal > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), jj ) ) + :( jj ) ); + const size_t jpos( ( IsLower::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), jend ) ) + :( jend ) ); + + for( size_t j=jbegin; j // Type of the scalar value + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + selectDefaultSubAssignKernel( DenseMatrix& 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::value ) + ?( max( ( IsStrictlyLower::value ? j+1UL : j ), ii ) ) + :( ii ) ); + const size_t ipos( ( IsUpper::value ) + ?( min( ( IsStrictlyUpper::value ? j : j+1UL ), iend ) ) + :( iend ) ); + + for( size_t i=ibegin; i // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + for( size_t i=0UL; i // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallSubAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ), j+SIMDSIZE*8UL, K ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*4UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i+1UL : i+2UL ), j+SIMDSIZE*2UL, K ) ) + :( IsStrictlyLower::value ? i+1UL : i+2UL ) ) + :( IsUpper::value ? min( j+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsUpper::value )?( min( j+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + const size_t kend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i+1UL : i+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ), j ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( IsLower::value ? j : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectSmallSubAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyUpper::value ? j : j+1UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeSubAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + const SIMDType factor( set( scalar ) ); + + for( size_t jj=0UL; jj::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*4UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+4UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+2UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE*2UL, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+SIMDSIZE, ktmp ) ):( ktmp ) ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( i+1UL ):( ktmp ), + ( IsUpper::value )?( min( j+1UL, ktmp ) ):( ktmp ) ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline EnableIf_< UseVectorizedDefaultKernel > + selectLargeSubAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + const SIMDType factor( set( scalar ) ); + + for( size_t ii=0UL; ii::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+2UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+4UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+2UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+1UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(scalar) ); + subAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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 > + smpAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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 > + smpSubAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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 A, C; + blaze::DynamicMatrix 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 + operator*( const DenseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TDMatDMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< TDMatDMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< TDMatDMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsAligned< TDMatDMatMultExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< TDMatDMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< TDMatDMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< TDMatDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< TDMatDMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< TDMatDMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< TDMatDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TDMatDVecMultExprTrait< TDMatDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseVector, IsColumnVector > + , TDMatDVecMultExprTrait_< MT1, DMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TDMatSVecMultExprTrait< TDMatDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsSparseVector, IsColumnVector > + , TDMatDVecMultExprTrait_< MT1, DMatSVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecTDMatMultExprTrait< VT, TDMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , TDVecDMatMultExprTrait_< TDVecTDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecTDMatMultExprTrait< VT, TDMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , TDVecDMatMultExprTrait_< TSVecTDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< TDMatDMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< TDMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< TDMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ MRT; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ VRT; //!< Result type of the right-hand side dense vector expression. + typedef ElementType_ MET; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ VET; //!< Element type of the right-hand side dense vector expression. + typedef CompositeType_ MCT; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value && IsSame::value && + IsBLASCompatible::value ) || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense vector expression. + enum : bool { evaluateVector = IsComputation::value || RequiresEvaluation::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::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::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef TDMatDVecMultExpr This; //!< Type of this TDMatDVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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, const MT, const MT& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, 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::value && + MT::simdEnabled && VT::simdEnabled && + HasSIMDAdd::value && + HasSIMDMult::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::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::value ) + { + return mat_(index,index) * vec_[index]; + } + else if( IsLower::value && ( index + 8UL < mat_.rows() ) ) + { + const size_t n( IsStrictlyLower::value ? index : index+1UL ); + return subvector( row( mat_, index ), 0UL, n ) * subvector( vec_, 0UL, n ); + } + else if( IsUpper::value && ( index > 8UL ) ) + { + const size_t begin( IsStrictlyUpper::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::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& 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::value ) || + ( IsComputation::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::value ) { + reset( y[0] ); + } + + if( !IsUpper::value ) + { + for( size_t i=( IsStrictlyLower::value ? 1UL : 0UL ); i::value && !IsStrictlyUpper::value ? 0UL : 1UL ); j::value ) + { + y[j] = A(j,j) * x[j]; + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) { + y[iend] = A(iend,j) * x[j]; + } + } + } + + if( IsStrictlyUpper::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 > + 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 > + 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::value || !IsPadded::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, N ) - ( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*3UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+1UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + ElementType value = ElementType(); + + for( size_t j=jbegin; j // Type of the right-hand side vector operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( min( itmp, ( IsStrictlyUpper::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::value ) + ?( max( ii, ( IsStrictlyLower::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 // Type of the right-hand side vector operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( y, x ); + trmv( y, A, ( IsLower::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& 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_ ); + + 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& 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::value ) || + ( IsComputation::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::value ) + { + y[j] += A(j,j) * x[j]; + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side vector operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, N ) - ( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, N ) - ( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*3UL, N ) - ( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, N ) - ( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1( y.load(i) ); + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+1UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + ElementType value = ElementType(); + + for( size_t j=jbegin; j // Type of the right-hand side vector operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( min( itmp, ( IsStrictlyUpper::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::value ) + ?( max( ii, ( IsStrictlyLower::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 // Type of the right-hand side vector operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( x ) ); + trmv( tmp, A, ( IsLower::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& 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::value ) || + ( IsComputation::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::value ) + { + y[j] -= A(j,j) * x[j]; + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side vector operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, N ) - ( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, N ) - ( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*3UL, N ) - ( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, N ) - ( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1( y.load(i) ); + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+1UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + ElementType value = ElementType(); + + for( size_t j=jbegin; j // Type of the right-hand side vector operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( min( itmp, ( IsStrictlyUpper::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::value ) + ?( max( ii, ( IsStrictlyLower::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 // Type of the right-hand side vector operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( x ) ); + trmv( tmp, A, ( IsLower::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& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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, ST, false > + : public DenseVector< DVecScalarMultExpr< TDMatDVecMultExpr, ST, false >, false > + , private VecScalarMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef TDMatDVecMultExpr MVM; //!< Type of the transpose dense matrix-dense vector multiplication expression. + typedef ResultType_ RES; //!< Result type of the dense matrix-dense vector multiplication expression. + typedef ResultType_ MRT; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ VRT; //!< Result type of the right-hand side dense vector expression. + typedef ElementType_ MET; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ VET; //!< Element type of the right-hand side dense vector expression. + typedef CompositeType_ MCT; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value && IsSame::value && + IsBLASCompatible::value ) || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense vector expression. + enum : bool { evaluateVector = IsComputation::value || RequiresEvaluation::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + !( IsBuiltin< ElementType_ >::value && IsComplex::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::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ + , T4 >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DVecScalarMultExpr This; //!< Type of this DVecScalarMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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 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::value && + MT::simdEnabled && VT::simdEnabled && + AreSIMDCombinable::value && + HasSIMDAdd::value && + HasSIMDMult::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::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_ A( vector_.leftOperand() ); + return ( !BLAZE_BLAS_IS_PARALLEL || + ( IsComputation::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& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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::value ) || + ( IsComputation::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::value ) { + reset( y[0] ); + } + + if( !IsUpper::value ) + { + for( size_t i=( IsStrictlyLower::value ? 1UL : 0UL ); i::value && !IsStrictlyUpper::value ? 0UL : 1UL ); j::value ) + { + y[j] = A(j,j) * x[j] * scalar; + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) { + y[iend] = A(iend,j) * x[j]; + } + } + } + + if( IsStrictlyUpper::value ) { + reset( y[M-1UL] ); + } + + if( !IsDiagonal::value ) + { + const size_t iend( IsStrictlyUpper::value ? M-1UL : M ); + for( size_t i=( IsStrictlyLower::value ? 1UL : 0UL ); i // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, N ) - ( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*3UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+1UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + ElementType value = ElementType(); + + for( size_t j=jbegin; j // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( min( itmp, ( IsStrictlyUpper::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::value ) + ?( max( ii, ( IsStrictlyLower::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 // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( y, scalar * x ); + trmv( y, A, ( IsLower::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& 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_ ); + + 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& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, N ) - ( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*3UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+1UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + ElementType value = ElementType(); + + for( size_t j=jbegin; j // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( min( itmp, ( IsStrictlyUpper::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::value ) + ?( max( ii, ( IsStrictlyLower::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 // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAddAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( scalar * x ) ); + trmv( tmp, A, ( IsLower::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& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, N ) - ( IsStrictlyLower::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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*3UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+SIMDSIZE, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + SIMDType xmm1; + + for( size_t j=jbegin; j::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( min( i+1UL, N ) - ( IsStrictlyLower::value ? 1UL : 0UL ) ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + ElementType value = ElementType(); + + for( size_t j=jbegin; j // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( min( itmp, ( IsStrictlyUpper::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::value ) + ?( max( ii, ( IsStrictlyLower::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 // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasSubAssignKernel( VT1& y, const MT1& A, const VT2& x, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( scalar * x ) ); + trmv( tmp, A, ( IsLower::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& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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 > + smpSubAssign( DenseVector& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 A; + blaze::DynamicVector 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, TDMatDVecMultExpr > + operator*( const DenseMatrix& mat, const DenseVector& vec ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~mat).columns() != (~vec).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" ); + } + + return TDMatDVecMultExpr( ~mat, ~vec ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT > +struct Size< TDMatDVecMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT > +struct IsAligned< TDMatDVecMultExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, bool AF > +struct SubvectorExprTrait< TDMatDVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private MatMatAddExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense matrix expression. + typedef ReturnType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef AddExprTrait_ 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 This; //!< Type of this TDMatSMatAddExpr instance. + typedef AddTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::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& 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::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& 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_ ); + + 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& 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& 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 > + smpAssign( DenseMatrix& 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::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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A; + blaze::CompressedMatrix B; + blaze::DynamicMatrix 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 + operator+( const DenseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TDMatSMatAddExpr( ~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 A; + blaze::DynamicMatrix B; + blaze::DynamicMatrix 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 + operator+( const SparseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TDMatSMatAddExpr( ~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, T3 > + operator+( const TDMatSMatAddExpr& lhs, const DenseMatrix& 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, T3 > + operator-( const TDMatSMatAddExpr& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return ( lhs.leftOperand() - (~rhs) ) + lhs.rightOperand(); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< TDMatSMatAddExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< TDMatSMatAddExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< TDMatSMatAddExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< TDMatSMatAddExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< TDMatSMatAddExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< TDMatSMatAddExpr > + : public BoolConstant< Or< And< IsUniLower, IsStrictlyLower > + , And< IsUniLower, IsStrictlyLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< TDMatSMatAddExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< TDMatSMatAddExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< TDMatSMatAddExpr > + : public BoolConstant< Or< And< IsUniUpper, IsStrictlyUpper > + , And< IsUniUpper, IsStrictlyUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< TDMatSMatAddExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatAddExprTrait< TDMatSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatSMatAddExprTrait_< TDMatDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatAddExprTrait< TDMatSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDMatSMatAddExprTrait_< TDMatTDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatSubExprTrait< TDMatSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatSMatAddExprTrait_< TDMatDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatSubExprTrait< TDMatSMatAddExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDMatSMatAddExprTrait_< TDMatTDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< TDMatSMatAddExpr, AF > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< TDMatSMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< TDMatSMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side sparse matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::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::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::value && + !IsResizable< ElementType_ >::value && + !( IsColumnMajorMatrix::value && IsResizable::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::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef TDMatSMatMultExpr This; //!< Type of this TDMatSMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 > + assign( DenseMatrix& 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_ ConstIterator; + + reset( C ); + + for( size_t j=0UL; j::value ) + { + for( ; element!=end; ++element ) { + C(j,element->index()) = A(j,j) * element->value(); + } + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( A.rows() ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( ; element!=end; ++element ) { + for( size_t i=ibegin; iindex()) ) ) + 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 > + 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 > + selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + reset( C ); + + size_t i( 0UL ); + + for( size_t j=0UL; j::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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; kindex() ); + 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; iindex() ); + const ET2 v1( element->value() ); + + for( i=ibegin; i // Type of the right-hand side matrix operand + static inline EnableIf_< UseDefaultKernel > + 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 > + selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_ ); + + const OppositeType_ 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 > + assign( SparseMatrix& 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_ ); + + 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 > + assign( Matrix& 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 > + addAssign( DenseMatrix& 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_ ConstIterator; + + size_t i( 0UL ); + + for( size_t j=0UL; j::value ) + { + for( ; element!=end; ++element ) { + C(j,element->index()) += A(j,j) * element->value(); + } + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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; iindex()) += 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( ; iindex()) += 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 > + 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 > + selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + size_t i( 0UL ); + + for( size_t j=0UL; j::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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; kindex() ); + 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; iindex() ); + const ET2 v1( element->value() ); + + for( i=ibegin; i // Type of the right-hand side matrix operand + static inline EnableIf_< UseDefaultKernel > + 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 > + selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_ ); + + const OppositeType_ 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 > + addAssign( Matrix& 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 > + subAssign( DenseMatrix& 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_ ConstIterator; + + size_t i( 0UL ); + + for( size_t j=0UL; j::value ) + { + for( ; element!=end; ++element ) { + C(j,element->index()) -= A(j,j) * element->value(); + } + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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; iindex()) -= 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( ; iindex()) -= 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 > + 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 > + selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + size_t i( 0UL ); + + for( size_t j=0UL; j::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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; kindex() ); + 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; iindex() ); + const ET2 v1( element->value() ); + + for( i=ibegin; i // Type of the right-hand side matrix operand + static inline EnableIf_< UseDefaultKernel > + 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 > + selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( OppositeType_ ); + + const OppositeType_ 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 > + subAssign( Matrix& 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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAssign( Matrix& 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 > + smpAddAssign( DenseMatrix& 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 > + smpAddAssign( Matrix& 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 > + smpSubAssign( DenseMatrix& 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 > + smpSubAssign( Matrix& 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 A, C; + blaze::CompressedMatrix 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 + operator*( const DenseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TDMatSMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< TDMatSMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< TDMatSMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsAligned< TDMatSMatMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< TDMatSMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< TDMatSMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< TDMatSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< TDMatSMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< TDMatSMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< TDMatSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TDMatDVecMultExprTrait< TDMatSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseVector, IsColumnVector > + , TDMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TDMatSVecMultExprTrait< TDMatSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsSparseVector, IsColumnVector > + , TDMatSVecMultExprTrait_< MT1, SMatSVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecTDMatMultExprTrait< VT, TDMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , TDMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecTDMatMultExprTrait< VT, TDMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , TDVecSMatMultExprTrait_< TSVecTDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< TDMatSMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< TDMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< TDMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private MatMatSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side dense matrix expression. + typedef ReturnType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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 This; //!< Type of this TDMatSMatSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::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& 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::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& 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_ ); + + 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& 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& 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 > + smpAssign( DenseMatrix& 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::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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A; + blaze::CompressedMatrix B; + blaze::DynamicMatrix 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 + operator-( const DenseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TDMatSMatSubExpr( ~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, T3 > + operator+( const TDMatSMatSubExpr& lhs, const DenseMatrix& 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, T3 > + operator-( const TDMatSMatSubExpr& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return ( lhs.leftOperand() - (~rhs) ) - lhs.rightOperand(); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< TDMatSMatSubExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< TDMatSMatSubExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< TDMatSMatSubExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< TDMatSMatSubExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< TDMatSMatSubExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< TDMatSMatSubExpr > + : public BoolConstant< And< IsUniLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< TDMatSMatSubExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< TDMatSMatSubExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< TDMatSMatSubExpr > + : public BoolConstant< And< IsUniUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< TDMatSMatSubExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatAddExprTrait< TDMatSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatSMatSubExprTrait_< TDMatDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatAddExprTrait< TDMatSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDMatSMatSubExprTrait_< TDMatTDMatAddExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatSubExprTrait< TDMatSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatSMatSubExprTrait_< TDMatDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatSubExprTrait< TDMatSMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDMatSMatSubExprTrait_< TDMatTDMatSubExprTrait_, MT2 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< TDMatSMatSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< TDMatSMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< TDMatSMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ MRT; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ VRT; //!< Result type of the right-hand side sparse vector expression. + typedef ElementType_ MET; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ VET; //!< Element type of the right-hand side sparse vector expression. + typedef CompositeType_ MCT; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense vector expression. + enum : bool { evaluateVector = IsComputation::value || RequiresEvaluation::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::value && + T1::simdEnabled && T2::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::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::value && + !IsDiagonal::value && + !IsResizable< ElementType_ >::value && + !IsResizable::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::value && + !UseOptimizedKernel::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef TDMatSVecMultExpr This; //!< Type of this TDMatSVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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, const MT, const MT& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, 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_ > RT; + //********************************************************************************************** + + //**Compilation flags*************************************************************************** + //! Compilation switch for the expression template evaluation strategy. + enum : bool { simdEnabled = !IsDiagonal::value && + MT::simdEnabled && + HasSIMDAdd::value && + HasSIMDMult::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::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::value ) + { + return mat_(index,index) * vec_[index]; + } + else if( IsLower::value ) + { + const size_t n( IsStrictlyLower::value ? index : index+1UL ); + return subvector( row( mat_, index ), 0UL, n ) * subvector( vec_, 0UL, n ); + } + else if( IsUpper::value ) + { + const size_t begin( IsStrictlyUpper::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& 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 > + selectAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ConstIterator_< RemoveReference_ > 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::value ) { + const size_t iend( IsStrictlyLower::value ? element->index()+1UL : element->index() ); + for( size_t i=0UL; iindex() ); + + if( IsDiagonal::value ) + { + for( size_t i=last; ivalue(); + last = index + 1UL; + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? index+1UL : index ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? index : index+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; ivalue(); + } + for( size_t i=last; ivalue(); + } + + last = iend; + } + } + + if( IsUpper::value ) { + for( size_t i=last; i // Type of the right-hand side vector operand + static inline EnableIf_< UseOptimizedKernel > + selectAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ConstIterator_< RemoveReference_ > 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; iindex() ); + const VET v1( element->value() ); + ++element; + + for( size_t i=0UL; i3UL)?(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::value ) + ?( IsStrictlyLower::value ? j1+1UL : j1 ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j4 : j4+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; iindex() ); + const VET v1( element->value() ); + + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j1+1UL : j1 ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j1 : j1+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i // Type of the right-hand side vector operand + static inline EnableIf_< UseVectorizedKernel > + selectAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" ); + + const size_t M( A.rows() ); + + const bool remainder( !IsPadded::value || !IsPadded::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( ; iindex() ); + 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( ; i3UL)?(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::value ) + ?( ( IsStrictlyLower::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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( ; iindex() ); + const VET v1( element->value() ); + + const SIMDType xmm1( set( v1 ) ); + + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the target sparse vector + friend inline void assign( SparseVector& 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_ ); + + 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& 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 > + selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ConstIterator_< RemoveReference_ > 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::value ) + { + y[index] += A(index,index) * element->value(); + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? index+1UL : index ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? index : index+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; ivalue(); + } + } + } + } + /*! \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 > + selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ConstIterator_< RemoveReference_ > 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::value ) + ?( IsStrictlyLower::value ? j1+1UL : j1 ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j4 : j4+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; iindex() ); + const VET v1( element->value() ); + + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j1+1UL : j1 ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j1 : j1+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i // Type of the right-hand side vector operand + static inline EnableIf_< UseVectorizedKernel > + selectAddAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" ); + + const size_t M( A.rows() ); + + const bool remainder( !IsPadded::value || !IsPadded::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::value ) + ?( ( IsStrictlyLower::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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( ; iindex() ); + const VET v1( element->value() ); + + const SIMDType xmm1( set( v1 ) ); + + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the target dense vector + friend inline void subAssign( DenseVector& 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 > + selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ConstIterator_< RemoveReference_ > 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::value ) + { + y[index] -= A(index,index) * element->value(); + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? index+1UL : index ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? index : index+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; ivalue(); + } + } + } + } + /*! \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 > + selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ConstIterator_< RemoveReference_ > 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::value ) + ?( IsStrictlyLower::value ? j1+1UL : j1 ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j4 : j4+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; iindex() ); + const VET v1( element->value() ); + + const size_t ibegin( ( IsLower::value ) + ?( IsStrictlyLower::value ? j1+1UL : j1 ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j1 : j1+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i // Type of the right-hand side vector operand + static inline EnableIf_< UseVectorizedKernel > + selectSubAssignKernel( VT1& y, const MT1& A, const VT2& x ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" ); + + const size_t M( A.rows() ); + + const bool remainder( !IsPadded::value || !IsPadded::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::value ) + ?( ( IsStrictlyLower::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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( ; iindex() ); + const VET v1( element->value() ); + + const SIMDType xmm1( set( v1 ) ); + + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the target dense vector + friend inline void multAssign( DenseVector& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 A; + blaze::CompressedVector x; + blaze::DynamicVector 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, TDMatSVecMultExpr > + operator*( const DenseMatrix& mat, const SparseVector& vec ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~mat).columns() != (~vec).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" ); + } + + return TDMatSVecMultExpr( ~mat, ~vec ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT > +struct Size< TDMatSVecMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT > +struct IsAligned< TDMatSVecMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, bool AF > +struct SubvectorExprTrait< TDMatSVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side dense matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::value && + ( IsSymmetric::value || IsSymmetric::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::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::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::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef TDMatTDMatMultExpr This; //!< Type of this TDMatTDMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side dense matrix expression. + typedef If_< IsExpression, 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::value && + MT1::simdEnabled && MT2::simdEnabled && + HasSIMDAdd::value && + HasSIMDMult::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::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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 > + assign( DenseMatrix& 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::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 >, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + if( IsStrictlyTriangular::value && kbegin == kend ) { + for( size_t i=0UL; i::value ) + ?( IsStrictlyLower::value ? kbegin+1UL : kbegin ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? kbegin : kbegin+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + if( IsLower::value && IsLower::value ) { + for( size_t i=0UL; i::value ) { + reset( C(0UL,j) ); + } + for( size_t i=ibegin; i::value && IsUpper::value ) { + for( size_t i=iend; i::value ) { + reset( C(M-1UL,j) ); + } + } + + for( size_t k=kbegin+1UL; k::value ) + ?( IsStrictlyLower::value ? k+1UL : k ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? k-1UL : k ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i::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 >, IsDiagonal > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + if( IsLower::value ) { + for( size_t i=0UL; i::value ) { + for( size_t i=iend; i // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + if( IsLower::value ) { + for( size_t i=0UL; i::value ) { + for( size_t i=iend; i // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + 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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAssignKernel( DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_ ); + + if( IsResizable::value && !IsResizable::value ) { + const OppositeType_ tmp( serial( B ) ); + assign( ~C, A * tmp ); + } + else if( !IsResizable::value && IsResizable::value ) { + const OppositeType_ tmp( serial( A ) ); + assign( ~C, tmp * B ); + } + else if( B.rows() * B.columns() <= A.rows() * A.columns() ) { + const OppositeType_ tmp( serial( B ) ); + assign( ~C, A * tmp ); + } + else { + const OppositeType_ 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 > + selectSmallAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyUpper::value ? j : j+1UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeAssignKernel( DenseMatrix& 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 > + selectLargeAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + for( size_t ii=0UL; ii::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i ,j) ); + SIMDType xmm2( (~C).load(i1,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+1UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( C, B ); + trmm( C, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(1) ); + } + else if( IsTriangular::value ) { + assign( C, A ); + trmm( C, B, CblasRight, ( IsLower::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 > + assign( SparseMatrix& 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_ ); + + 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 > + assign( Matrix& 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::value && IsSymmetric::value ) + assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + addAssign( DenseMatrix& 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::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 >, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + for( size_t k=kbegin; k::value ) + ?( IsStrictlyLower::value ? k+1UL : k ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 ); + + for( size_t i=0UL; i // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAddAssignKernel( DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_ ); + + if( IsResizable::value && !IsResizable::value ) { + const OppositeType_ tmp( serial( B ) ); + addAssign( ~C, A * tmp ); + } + else if( !IsResizable::value && IsResizable::value ) { + const OppositeType_ tmp( serial( A ) ); + addAssign( ~C, tmp * B ); + } + else if( B.rows() * B.columns() <= A.rows() * A.columns() ) { + const OppositeType_ tmp( serial( B ) ); + addAssign( ~C, A * tmp ); + } + else { + const OppositeType_ 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 > + selectSmallAddAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyUpper::value ? j : j+1UL ) ) + :( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + ElementType value1( (~C)(i,j ) ); + ElementType value2( (~C)(i,j+1UL) ); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeAddAssignKernel( DenseMatrix& 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 > + selectLargeAddAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + for( size_t ii=0UL; ii::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i ,j) ); + SIMDType xmm2( (~C).load(i1,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+1UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(1) ); + addAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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 > + addAssign( Matrix& 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::value && IsSymmetric::value ) + addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + subAssign( DenseMatrix& 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::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 >, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + for( size_t k=kbegin; k::value ) + ?( IsStrictlyLower::value ? k+1UL : k ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + selectDefaultSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + BLAZE_CONSTRAINT_MUST_BE_COLUMN_MAJOR_MATRIX_TYPE( MT3 ); + + for( size_t i=0UL; i // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallSubAssignKernel( DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_ ); + + if( IsResizable::value && !IsResizable::value ) { + const OppositeType_ tmp( serial( B ) ); + subAssign( ~C, A * tmp ); + } + else if( !IsResizable::value && IsResizable::value ) { + const OppositeType_ tmp( serial( A ) ); + subAssign( ~C, tmp * B ); + } + else if( B.rows() * B.columns() <= A.rows() * A.columns() ) { + const OppositeType_ tmp( serial( B ) ); + subAssign( ~C, A * tmp ); + } + else { + const OppositeType_ 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 > + selectSmallSubAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyUpper::value ? j : j+1UL ) ) + :( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + ElementType value1( (~C)(i,j ) ); + ElementType value2( (~C)(i,j+1UL) ); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeSubAssignKernel( DenseMatrix& 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 > + selectLargeSubAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + for( size_t ii=0UL; ii::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::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::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i ,j) ); + SIMDType xmm2( (~C).load(i1,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1( (~C).load(i,j) ); + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+1UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + ElementType value( (~C)(i,j) ); + + for( size_t k=kbegin; k // Type of the right-hand side matrix operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(1) ); + subAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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 > + subAssign( Matrix& 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::value && IsSymmetric::value ) + subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAssign( Matrix& 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::value && IsSymmetric::value ) + smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + smpAddAssign( DenseMatrix& 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 > + smpAddAssign( Matrix& 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::value && IsSymmetric::value ) + smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + smpSubAssign( DenseMatrix& 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 > + smpSubAssign( Matrix& 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::value && IsSymmetric::value ) + smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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, ST, true > + : public DenseMatrix< DMatScalarMultExpr< TDMatTDMatMultExpr, ST, true >, true > + , private MatScalarMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef TDMatTDMatMultExpr MMM; //!< Type of the dense matrix multiplication expression. + typedef ResultType_ RES; //!< Result type of the dense matrix multiplication expression. + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side dense matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::value && + ( IsSymmetric::value || IsSymmetric::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::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + !( IsBuiltin< ElementType_ >::value && IsComplex::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::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ + , T4 >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DMatScalarMultExpr This; //!< Type of this DMatScalarMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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 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::value && + MT1::simdEnabled && MT2::simdEnabled && + AreSIMDCombinable::value && + HasSIMDAdd::value && + HasSIMDMult::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::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_ 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 > + assign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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::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 >, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( K ) ); + BLAZE_INTERNAL_ASSERT( kbegin <= kend, "Invalid loop indices detected" ); + + if( IsStrictlyTriangular::value && kbegin == kend ) { + for( size_t i=0UL; i::value ) + ?( IsStrictlyLower::value ? kbegin+1UL : kbegin ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? kbegin : kbegin+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + if( IsLower::value && IsLower::value ) { + for( size_t i=0UL; i::value ) { + reset( C(0UL,j) ); + } + for( size_t i=ibegin; i::value && IsUpper::value ) { + for( size_t i=iend; i::value ) { + reset( C(M-1UL,j) ); + } + } + + for( size_t k=kbegin+1UL; k::value ) + ?( IsStrictlyLower::value ? k+1UL : k ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? k-1UL : k ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i::value ) { + C(iend,j) = A(iend,k) * B(k,j); + } + } + + { + const size_t ibegin( ( IsLower::value && IsLower::value ) + ?( IsStrictlyLower::value || IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value && IsUpper::value ) + ?( IsStrictlyUpper::value || IsStrictlyUpper::value ? j : j+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; i // Type of the scalar value + static inline EnableIf_< And< Not< IsDiagonal >, IsDiagonal > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + if( IsLower::value ) { + for( size_t i=0UL; i::value ) { + for( size_t i=iend; i // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + if( IsLower::value ) { + for( size_t i=0UL; i::value ) { + for( size_t i=iend; i // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + 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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAssignKernel( DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_ ); + + if( IsResizable::value && !IsResizable::value ) { + const OppositeType_ tmp( serial( B ) ); + assign( ~C, A * tmp * scalar ); + } + else if( !IsResizable::value && IsResizable::value ) { + const OppositeType_ tmp( serial( A ) ); + assign( ~C, tmp * B * scalar ); + } + else if( B.rows() * B.columns() <= A.rows() * A.columns() ) { + const OppositeType_ tmp( serial( B ) ); + assign( ~C, A * tmp * scalar ); + } + else { + const OppositeType_ 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 > + selectSmallAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyUpper::value ? j : j+1UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeAssignKernel( DenseMatrix& 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 > + selectLargeAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + const SIMDType factor( set( scalar ) ); + + for( size_t ii=0UL; ii::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+2UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+4UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+2UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+1UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( C, B ); + trmm( C, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(scalar) ); + } + else if( IsTriangular::value ) { + assign( C, A ); + trmm( C, B, CblasRight, ( IsLower::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 > + assign( SparseMatrix& 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_ ); + + 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 > + assign( Matrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ right( rhs.matrix_.rightOperand() ); + + if( IsSymmetric::value && IsSymmetric::value ) + assign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ ); + else if( IsSymmetric::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 > + addAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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::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 >, Not< IsDiagonal > > > + 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 >, IsDiagonal > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + 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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallAddAssignKernel( DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_ ); + + if( IsResizable::value && !IsResizable::value ) { + const OppositeType_ tmp( serial( B ) ); + addAssign( ~C, A * tmp * scalar ); + } + else if( !IsResizable::value && IsResizable::value ) { + const OppositeType_ tmp( serial( A ) ); + addAssign( ~C, tmp * B * scalar ); + } + else if( B.rows() * B.columns() <= A.rows() * A.columns() ) { + const OppositeType_ tmp( serial( B ) ); + addAssign( ~C, A * tmp * scalar ); + } + else { + const OppositeType_ 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 > + selectSmallAddAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyUpper::value ? j : j+1UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeAddAssignKernel( DenseMatrix& 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 > + selectLargeAddAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + const SIMDType factor( set( scalar ) ); + + for( size_t ii=0UL; ii::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+2UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+4UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+2UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+1UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAddAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(scalar) ); + addAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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 > + addAssign( Matrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ right( rhs.matrix_.rightOperand() ); + + if( IsSymmetric::value && IsSymmetric::value ) + addAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ ); + else if( IsSymmetric::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 > + subAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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::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 >, Not< IsDiagonal > > > + 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 >, IsDiagonal > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, Not< IsDiagonal > > > + 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline EnableIf_< And< IsDiagonal, IsDiagonal > > + 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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectSmallSubAssignKernel( DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_ ); + + if( IsResizable::value && !IsResizable::value ) { + const OppositeType_ tmp( serial( B ) ); + subAssign( ~C, A * tmp * scalar ); + } + else if( !IsResizable::value && IsResizable::value ) { + const OppositeType_ tmp( serial( A ) ); + subAssign( ~C, tmp * B * scalar ); + } + else if( B.rows() * B.columns() <= A.rows() * A.columns() ) { + const OppositeType_ tmp( serial( B ) ); + subAssign( ~C, A * tmp * scalar ); + } + else { + const OppositeType_ 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 > + selectSmallSubAssignKernel( DenseMatrix& 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::value || !IsPadded::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::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*8UL, K, ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyUpper::value ? j : j+1UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*8UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*4UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*4UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*4UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( min( i+SIMDSIZE*2UL, K, ( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) ) + :( IsStrictlyUpper::value ? j+1UL : j+2UL ) ) + :( IsLower::value ? min( i+SIMDSIZE*2UL, K ) : K ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsLower::value )?( min( i+SIMDSIZE*2UL, K ) ):( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + const size_t kend( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j+1UL : j+2UL ) + :( K ) ); + + ElementType value1 = ElementType(); + ElementType value2 = ElementType(); + + for( size_t k=kbegin; k::value ) + ?( ( IsUpper::value ) + ?( max( i, ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyLower::value ? j+1UL : j ) ) + :( IsUpper::value ? i : 0UL ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + selectLargeSubAssignKernel( DenseMatrix& 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 > + selectLargeSubAssignKernel( DenseMatrix& 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::value || !IsPadded::value ); + + const SIMDType factor( set( scalar ) ); + + for( size_t ii=0UL; ii::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+2UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*4UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+4UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7, xmm8; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+2UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE*2UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1, xmm2; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+SIMDSIZE, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + SIMDType xmm1; + + for( size_t k=kbegin; k::value )?( max( i, kk ) ):( kk ), + ( IsLower::value )?( max( j, kk ) ):( kk ) ) ); + const size_t kend ( min( ( IsLower::value )?( min( i+1UL, ktmp ) ):( ktmp ), + ( IsUpper::value )?( j+1UL ):( ktmp ) ) ); + + ElementType value = ElementType(); + + for( size_t k=kbegin; k // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasSubAssignKernel( MT3& C, const MT4& A, const MT5& B, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( B ) ); + trmm( tmp, A, CblasLeft, ( IsLower::value )?( CblasLower ):( CblasUpper ), ET(scalar) ); + subAssign( C, tmp ); + } + else if( IsTriangular::value ) { + ResultType_ tmp( serial( A ) ); + trmm( tmp, B, CblasRight, ( IsLower::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 > + subAssign( Matrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ right( rhs.matrix_.rightOperand() ); + + if( IsSymmetric::value && IsSymmetric::value ) + subAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ ); + else if( IsSymmetric::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 > + smpAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAssign( Matrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ right( rhs.matrix_.rightOperand() ); + + if( IsSymmetric::value && IsSymmetric::value ) + smpAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ ); + else if( IsSymmetric::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 > + smpAddAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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 > + smpAddAssign( Matrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ right( rhs.matrix_.rightOperand() ); + + if( IsSymmetric::value && IsSymmetric::value ) + smpAddAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ ); + else if( IsSymmetric::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 > + smpSubAssign( DenseMatrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ 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 > + smpSubAssign( Matrix& 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_ left ( rhs.matrix_.leftOperand() ); + RightOperand_ right( rhs.matrix_.rightOperand() ); + + if( IsSymmetric::value && IsSymmetric::value ) + smpSubAssign( ~lhs, trans( left ) * trans( right ) * rhs.scalar_ ); + else if( IsSymmetric::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 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 + operator*( const DenseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TDMatTDMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< TDMatTDMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< TDMatTDMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsAligned< TDMatTDMatMultExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< TDMatTDMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< TDMatTDMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< TDMatTDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< TDMatTDMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< TDMatTDMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< TDMatTDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TDMatDVecMultExprTrait< TDMatTDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector > + , TDMatDVecMultExprTrait_< MT1, TDMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TDMatSVecMultExprTrait< TDMatTDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector > + , TDMatDVecMultExprTrait_< MT1, TDMatSVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecTDMatMultExprTrait< VT, TDMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDVecTDMatMultExprTrait_< TDVecTDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecTDMatMultExprTrait< VT, TDMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDVecTDMatMultExprTrait_< TSVecTDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< TDMatTDMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< TDMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< TDMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side dense matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side dense matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side sparse matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::value && + T1::simdEnabled && T2::simdEnabled && + IsColumnMajorMatrix::value && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::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::value && + !IsDiagonal::value && + !IsResizable< ElementType_ >::value && + !IsResizable::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::value && + !UseOptimizedKernel::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef TDMatTSMatMultExpr This; //!< Type of this TDMatTSMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::value && + MT1::simdEnabled && + HasSIMDAdd::value && + HasSIMDMult::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::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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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& 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 > + selectAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( Or< IsColumnMajorMatrix, IsDiagonal >::value ? A.rows() : 64UL ); + + reset( C ); + + for( size_t ii=0UL; iiindex() ); + + if( IsDiagonal::value ) + { + C(j1,j) = A(j1,j1) * element->value(); + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( max( ii, ( IsStrictlyLower::value ? j1+1UL : j1 ) ) ) + :( ii ) ); + const size_t iend( ( IsUpper::value ) + ?( min( itmp, ( IsStrictlyUpper::value ? j1 : j1+1UL ) ) ) + :( itmp ) ); + + if( IsTriangular::value && ibegin >= iend ) + continue; + + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + for( size_t i=ibegin; ivalue(); + 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 > + selectAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsColumnMajorMatrix::value ? A.rows() : 64UL ); + + reset( C ); + + for( size_t ii=0UL; iiindex() ); + 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::value ) + ?( max( ii, ( IsStrictlyLower::value ? j1+1UL : j1 ) ) ) + :( ii ) ); + const size_t iend( ( IsUpper::value ) + ?( min( itmp, ( IsStrictlyUpper::value ? j4 : j4+1UL ) ) ) + :( itmp ) ); + + if( IsTriangular::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; iindex() ); + const ET2 v1( element->value() ); + + const size_t ibegin( ( IsLower::value ) + ?( max( ii, ( IsStrictlyLower::value ? j1+1UL : j1 ) ) ) + :( ii ) ); + const size_t iend( ( IsUpper::value ) + ?( min( itmp, ( IsStrictlyUpper::value ? j1 : j1+1UL ) ) ) + :( itmp ) ); + + if( IsTriangular::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 // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedKernel > + selectAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const bool remainder( !IsPadded::value || !IsPadded::value ); + + reset( C ); + + for( size_t j=0UL; jindex() ); + 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::value ) + ?( ( IsStrictlyLower::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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( ; iindex() ); + const ET2 v1( element->value() ); + + const SIMDType xmm1( set( v1 ) ); + + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Storage order of the target sparse matrix + friend inline void assign( SparseMatrix& 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_ ); + + 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& 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 > + selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( Or< IsColumnMajorMatrix, IsDiagonal >::value ? A.rows() : 64UL ); + + for( size_t ii=0UL; iiindex() ); + + if( IsDiagonal::value ) + { + C(j1,j) += A(j1,j1) * element->value(); + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( max( ii, ( IsStrictlyLower::value ? j1+1UL : j1 ) ) ) + :( ii ) ); + const size_t iend( ( IsUpper::value ) + ?( min( itmp, ( IsStrictlyUpper::value ? j1 : j1+1UL ) ) ) + :( itmp ) ); + + if( IsTriangular::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; ivalue(); + 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; ivalue(); + } + } + } + } + } + } + /*! \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 > + selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsColumnMajorMatrix::value ? A.rows() : 64UL ); + + for( size_t ii=0UL; iiindex() ); + 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::value ) + ?( max( ii, ( IsStrictlyLower::value ? j1+1UL : j1 ) ) ) + :( ii ) ); + const size_t iend( ( IsUpper::value ) + ?( min( itmp, ( IsStrictlyUpper::value ? j4 : j4+1UL ) ) ) + :( itmp ) ); + + if( IsTriangular::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; iindex() ); + const ET2 v1( element->value() ); + + const size_t ibegin( ( IsLower::value ) + ?( max( ii, ( IsStrictlyLower::value ? j1+1UL : j1 ) ) ) + :( ii ) ); + const size_t iend( ( IsUpper::value ) + ?( min( itmp, ( IsStrictlyUpper::value ? j1 : j1+1UL ) ) ) + :( itmp ) ); + + if( IsTriangular::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 // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedKernel > + selectAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const bool remainder( !IsPadded::value || !IsPadded::value ); + + for( size_t j=0UL; jindex() ); + 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::value ) + ?( ( IsStrictlyLower::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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( ; iindex() ); + const ET2 v1( element->value() ); + + const SIMDType xmm1( set( v1 ) ); + + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Storage order of the target dense matrix + friend inline void subAssign( DenseMatrix& 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 > + selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( Or< IsColumnMajorMatrix, IsDiagonal >::value ? A.rows() : 64UL ); + + for( size_t ii=0UL; iiindex() ); + + if( IsDiagonal::value ) + { + C(j1,j) -= A(j1,j1) * element->value(); + } + else + { + const size_t ibegin( ( IsLower::value ) + ?( max( ii, ( IsStrictlyLower::value ? j1+1UL : j1 ) ) ) + :( ii ) ); + const size_t iend( ( IsUpper::value ) + ?( min( itmp, ( IsStrictlyUpper::value ? j1 : j1+1UL ) ) ) + :( itmp ) ); + + if( IsTriangular::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; ivalue(); + 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; ivalue(); + } + } + } + } + } + } + /*! \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 > + selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsColumnMajorMatrix::value ? A.rows() : 64UL ); + + for( size_t ii=0UL; iiindex() ); + 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::value ) + ?( max( ii, ( IsStrictlyLower::value ? j1+1UL : j1 ) ) ) + :( ii ) ); + const size_t iend( ( IsUpper::value ) + ?( min( itmp, ( IsStrictlyUpper::value ? j4 : j4+1UL ) ) ) + :( itmp ) ); + + if( IsTriangular::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; iindex() ); + const ET2 v1( element->value() ); + + const size_t ibegin( ( IsLower::value ) + ?( max( ii, ( IsStrictlyLower::value ? j1+1UL : j1 ) ) ) + :( ii ) ); + const size_t iend( ( IsUpper::value ) + ?( min( itmp, ( IsStrictlyUpper::value ? j1 : j1+1UL ) ) ) + :( itmp ) ); + + if( IsTriangular::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 // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedKernel > + selectSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const bool remainder( !IsPadded::value || !IsPadded::value ); + + for( size_t j=0UL; jindex() ); + 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::value ) + ?( ( IsStrictlyLower::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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( ; iindex() ); + const ET2 v1( element->value() ); + + const SIMDType xmm1( set( v1 ) ); + + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j1+1UL : j1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Storage order of the target dense matrix + friend inline EnableIf_< IsEvaluationRequired > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A, C; + blaze::CompressedMatrix 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 + operator*( const DenseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TDMatTSMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< TDMatTSMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< TDMatTSMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsAligned< TDMatTSMatMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< TDMatTSMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< TDMatTSMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< TDMatTSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< TDMatTSMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< TDMatTSMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< TDMatTSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TDMatDVecMultExprTrait< TDMatTSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector > + , TDMatDVecMultExprTrait_< MT1, TSMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TDMatSVecMultExprTrait< TDMatTSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector > + , TDMatDVecMultExprTrait_< MT1, TSMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecTDMatMultExprTrait< VT, TDMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , TDVecTSMatMultExprTrait_< TDVecTDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecTDMatMultExprTrait< VT, TDMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , TDVecTSMatMultExprTrait_< TSVecTDMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< TDMatTSMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< TDMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< TDMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private TVecMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ VRT; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ MRT; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ VET; //!< Element type of the left-hand side dense vector epxression. + typedef ElementType_ MET; //!< Element type of the right-hand side dense matrix expression. + typedef CompositeType_ VCT; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateMatrix = ( IsComputation::value && IsSame::value && + IsBLASCompatible::value ) || RequiresEvaluation::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::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::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef TDVecDMatMultExpr This; //!< Type of this TDVecDMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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, const VT, const VT& > LeftOperand; + + //! Composite type of the right-hand side dense matrix expression. + typedef If_< IsExpression, 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::value && + VT::simdEnabled && MT::simdEnabled && + HasSIMDAdd::value && + HasSIMDMult::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::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::value ) + { + return vec_[index] * mat_(index,index); + } + else if( IsLower::value && ( index > 8UL ) ) + { + const size_t begin( IsStrictlyLower::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::value && ( index + 8UL < mat_.rows() ) ) + { + const size_t n( IsStrictlyUpper::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::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& 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::value ) || + ( IsComputation::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::value ) { + reset( y[0] ); + } + + if( !IsLower::value ) + { + const size_t jbegin( IsStrictlyUpper::value ? 1UL : 0UL ); + for( size_t j=jbegin; j::value && !IsStrictlyLower::value ? 0UL : 1UL ); i::value ) + { + y[i] = x[i] * A(i,i); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) { + y[jend] = x[i] * A(i,jend); + } + } + } + + if( IsStrictlyLower::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 > + 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 > + 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::value || !IsPadded::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*8UL, M ) - ( IsStrictlyUpper::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*4UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*3UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*2UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+1UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + ElementType value = ElementType(); + + for( size_t i=ibegin; i // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( min( jtmp, ( IsStrictlyLower::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::value ) + ?( max( jj, ( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( y, x ); + trmv( y, A, ( IsLower::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& 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_ ); + + 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& 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::value ) || + ( IsComputation::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::value ) + { + y[i] += x[i] * A(i,i); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*8UL, M ) - ( IsStrictlyUpper::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*4UL, M ) - ( IsStrictlyUpper::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*3UL, M ) - ( IsStrictlyUpper::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*2UL, M ) - ( IsStrictlyUpper::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1( y.load(j) ); + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+1UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + ElementType value = ElementType(); + + for( size_t i=ibegin; i // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( min( jtmp, ( IsStrictlyLower::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::value ) + ?( max( jj, ( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( x ) ); + trmv( tmp, A, ( IsLower::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& 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::value ) || + ( IsComputation::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::value ) + { + y[i] -= x[i] * A(i,i); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*8UL, M ) - ( IsStrictlyUpper::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*4UL, M ) - ( IsStrictlyUpper::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*3UL, M ) - ( IsStrictlyUpper::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*2UL, M ) - ( IsStrictlyUpper::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1( y.load(j) ); + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+1UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + ElementType value = ElementType(); + + for( size_t i=ibegin; i // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( min( jtmp, ( IsStrictlyLower::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::value ) + ?( max( jj, ( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( x ) ); + trmv( tmp, A, ( IsLower::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& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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, ST, true > + : public DenseVector< DVecScalarMultExpr< TDVecDMatMultExpr, ST, true >, true > + , private VecScalarMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef TDVecDMatMultExpr VMM; //!< Type of the dense vector-dense matrix multiplication expression. + typedef ResultType_ RES; //!< Result type of the dense vector-dense matrix multiplication expression. + typedef ResultType_ VRT; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ MRT; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ VET; //!< Element type of the left-hand side dense vector epxression. + typedef ElementType_ MET; //!< Element type of the right-hand side dense matrix expression. + typedef CompositeType_ VCT; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateMatrix = ( IsComputation::value && IsSame::value && + IsBLASCompatible::value ) || RequiresEvaluation::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + !( IsBuiltin< ElementType_ >::value && IsComplex::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::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ + , T4 >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DVecScalarMultExpr This; //!< Type of this DVecScalarMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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 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::value && + VT::simdEnabled && MT::simdEnabled && + AreSIMDCombinable::value && + HasSIMDAdd::value && + HasSIMDMult::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::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_ A( vector_.rightOperand() ); + return ( !BLAZE_BLAS_IS_PARALLEL || + ( IsComputation::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& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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::value ) || + ( IsComputation::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::value ) { + reset( y[0] ); + } + + if( !IsLower::value ) + { + for( size_t j=( IsStrictlyUpper::value ? 1UL : 0UL ); j::value && !IsStrictlyLower::value ? 0UL : 1UL ); i::value ) + { + y[i] = x[i] * A(i,i) * scalar; + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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::value ) { + y[jend] = x[i] * A(i,jend); + } + } + } + + if( IsStrictlyLower::value ) { + reset( y[N-1UL] ); + } + + if( !IsDiagonal::value ) + { + const size_t iend( IsStrictlyLower::value ? N-1UL : N ); + for( size_t j=( IsStrictlyUpper::value ? 1UL : 0UL ); j // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*8UL, M ) - ( IsStrictlyUpper::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*4UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*3UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*2UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+1UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + ElementType value = ElementType(); + + for( size_t i=ibegin; i // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( min( jtmp, ( IsStrictlyLower::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::value ) + ?( max( jj, ( IsStrictlyUpper::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 // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( y, scalar * x ); + trmv( y, A, ( IsLower::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& 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_ ); + + 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& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*8UL, M ) - ( IsStrictlyUpper::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*4UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*3UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*2UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+1UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + ElementType value = ElementType(); + + for( size_t i=ibegin; i // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( min( jtmp, ( IsStrictlyLower::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::value ) + ?( max( jj, ( IsStrictlyUpper::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 // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( scalar * x ) ); + trmv( tmp, A, ( IsLower::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& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*8UL, M ) - ( IsStrictlyUpper::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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*4UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3, xmm4; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*3UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2, xmm3; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE*2UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1, xmm2; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+SIMDSIZE, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + SIMDType xmm1; + + for( size_t i=ibegin; i::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( min( j+1UL, M ) - ( IsStrictlyUpper::value ? 1UL : 0UL ) ) + :( M ) ); + BLAZE_INTERNAL_ASSERT( ibegin <= iend, "Invalid loop indices detected" ); + + ElementType value = ElementType(); + + for( size_t i=ibegin; i // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::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::value ) + ?( min( jtmp, ( IsStrictlyLower::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::value ) + ?( max( jj, ( IsStrictlyUpper::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 // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( scalar * x ) ); + trmv( tmp, A, ( IsLower::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& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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 > + smpSubAssign( DenseVector& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 x, y; + blaze::DynamicMatrix 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, TDVecDMatMultExpr > + operator*( const DenseVector& vec, const DenseMatrix& mat ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~vec).size() != (~mat).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" ); + } + + return TDVecDMatMultExpr( ~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, MultExprTrait_ > + operator*( const DenseVector& vec, const DenseMatrix& 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 > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT > +struct IsAligned< TDVecDMatMultExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, bool AF > +struct SubvectorExprTrait< TDVecDMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ > CT1; + + //! Composite type of the right-hand side dense vector expression. + typedef RemoveReference_< CompositeType_ > CT2; + //********************************************************************************************** + + //********************************************************************************************** + enum : bool { value = useOptimizedKernels && + CT1::simdEnabled && + CT2::simdEnabled && + IsSame< ElementType_, ElementType_ >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::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 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 + , const MultTrait_< ElementType_, ElementType_ > > + operator*( const DenseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + typedef CompositeType_ Lhs; + typedef CompositeType_ Rhs; + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef MultTrait_ 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 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 + , const MultTrait_< ElementType_, ElementType_ > > + operator*( const DenseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + typedef CompositeType_ Lhs; + typedef CompositeType_ Rhs; + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef MultTrait_ MultType; + + enum : size_t { SIMDSIZE = SIMDTrait::size }; + + if( (~lhs).size() == 0UL ) return MultType(); + + Lhs left ( ~lhs ); + Rhs right( ~rhs ); + + const size_t N( left.size() ); + + SIMDTrait_ 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private TVecMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ VRT; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ MRT; //!< Result type of the right-hand side sparse matrix expression. + typedef CompositeType_ VCT; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side sparse matrix expression. + enum : bool { evaluateMatrix = RequiresEvaluation::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 This; //!< Type of this TDVecSMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT, const VT& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::value ) + { + return vec_[index] * mat_(index,index); + } + else if( IsLower::value ) + { + const size_t begin( IsStrictlyLower::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::value ) + { + const size_t n( IsStrictlyUpper::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& 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_ > ConstIterator; + + for( size_t i=0UL; i >::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& 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_ ); + + 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& 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_ > ConstIterator; + + for( size_t i=0UL; iindex()] += 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& 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_ > ConstIterator; + + for( size_t i=0UL; iindex()] -= 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& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 x, y; + blaze::CompressedMatrix 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, IsMatMatMultExpr >, TDVecSMatMultExpr > + operator*( const DenseVector& vec, const SparseMatrix& mat ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~vec).size() != (~mat).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" ); + } + + return TDVecSMatMultExpr( ~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, MultExprTrait_ > + operator*( const DenseVector& vec, const SparseMatrix& 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, MultExprTrait_ > + operator*( const DenseVector& vec, const SparseMatrix& 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 > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT > +struct IsAligned< TDVecSMatMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, bool AF > +struct SubvectorExprTrait< TDVecSMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 a; + blaze::CompressedVector 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_, ElementType_ > + operator*( const DenseVector& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + typedef CompositeType_ Lhs; // Composite type of the left-hand side dense vector expression + typedef CompositeType_ Rhs; // Composite type of the right-hand side sparse vector expression + typedef RemoveReference_ X1; // Auxiliary type for the left-hand side composite type + typedef RemoveReference_ X2; // Auxiliary type for the right-hand side composite type + typedef ElementType_ ET1; // Element type of the left-hand side dense vector expression + typedef ElementType_ ET2; // Element type of the right-hand side sparse vector expression + typedef MultTrait_ MultType; // Multiplication result type + typedef ConstIterator_ 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private TVecMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ VRT; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ MRT; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ VET; //!< Element type of the left-hand side dense vector epxression. + typedef ElementType_ MET; //!< Element type of the right-hand side dense matrix expression. + typedef CompositeType_ VCT; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateMatrix = ( IsComputation::value && IsSame::value && + IsBLASCompatible::value ) || RequiresEvaluation::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::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::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef TDVecTDMatMultExpr This; //!< Type of this TDVecTDMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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, const VT, const VT& > LeftOperand; + + //! Composite type of the right-hand side dense matrix expression. + typedef If_< IsExpression, 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::value && + VT::simdEnabled && MT::simdEnabled && + HasSIMDAdd::value && + HasSIMDMult::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::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::value ) + { + return vec_[index] * mat_(index,index); + } + else if( IsLower::value && ( index > 8UL ) ) + { + const size_t begin( IsStrictlyLower::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::value && ( index + 8UL < mat_.rows() ) ) + { + const size_t n( IsStrictlyUpper::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::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& 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::value ); + + size_t j( 0UL ); + + for( ; (j+8UL) <= N; j+=8UL ) + { + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::value ); + + reset( y ); + + size_t j( 0UL ); + + for( ; (j+8UL) <= N; j+=8UL ) + { + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( y, x ); + trmv( y, A, ( IsLower::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& 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_ ); + + 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& 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::value ); + + size_t j( 0UL ); + + for( ; (j+8UL) <= N; j+=8UL ) + { + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::value ); + + size_t j( 0UL ); + + for( ; (j+8UL) <= N; j+=8UL ) + { + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( x ) ); + trmv( tmp, A, ( IsLower::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& 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::value ); + + size_t j( 0UL ); + + for( ; (j+8UL) <= N; j+=8UL ) + { + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::value ); + + size_t j( 0UL ); + + for( ; (j+8UL) <= N; j+=8UL ) + { + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the right-hand side matrix operand + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( x ) ); + trmv( tmp, A, ( IsLower::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& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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, ST, true > + : public DenseVector< DVecScalarMultExpr< TDVecTDMatMultExpr, ST, true >, true > + , private VecScalarMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef TDVecTDMatMultExpr VMM; //!< Type of the dense vector-dense matrix multiplication expression. + typedef ResultType_ RES; //!< Result type of the dense vector-dense matrix multiplication expression. + typedef ResultType_ VRT; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ MRT; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ VET; //!< Element type of the left-hand side dense vector epxression. + typedef ElementType_ MET; //!< Element type of the right-hand side dense matrix expression. + typedef CompositeType_ VCT; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateMatrix = ( IsComputation::value && IsSame::value && + IsBLASCompatible::value ) || RequiresEvaluation::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::value && + HasConstDataAccess::value && + HasConstDataAccess::value && + !IsDiagonal::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsBLASCompatible< ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + IsSame< ElementType_, ElementType_ >::value && + !( IsBuiltin< ElementType_ >::value && IsComplex::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::value && + T1::simdEnabled && T2::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ + , T4 >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::value }; + }; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef DVecScalarMultExpr This; //!< Type of this DVecScalarMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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 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::value && + VT::simdEnabled && MT::simdEnabled && + AreSIMDCombinable::value && + HasSIMDAdd::value && + HasSIMDMult::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::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_ A( vector_.rightOperand() ); + return ( !BLAZE_BLAS_IS_PARALLEL || + ( IsComputation::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& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::value ); + + size_t j( 0UL ); + + for( ; (j+8UL) <= N; j+=8UL ) + { + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::value ); + + reset( y ); + + size_t j( 0UL ); + + for( ; (j+8UL) <= N; j+=8UL ) + { + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + assign( y, scalar * x ); + trmv( y, A, ( IsLower::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& 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_ ); + + 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& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::value ); + + size_t j( 0UL ); + + for( ; (j+8UL) <= N; j+=8UL ) + { + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::value ); + + size_t j( 0UL ); + + for( ; (j+8UL) <= N; j+=8UL ) + { + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasAddAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( scalar * x ) ); + trmv( tmp, A, ( IsLower::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& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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::value ) || + ( IsComputation::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 > + 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 > + 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::value || !IsPadded::value ); + + size_t j( 0UL ); + + for( ; (j+8UL) <= N; j+=8UL ) + { + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline DisableIf_< UseVectorizedDefaultKernel > + 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 > + 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::value || !IsPadded::value ); + + size_t j( 0UL ); + + for( ; (j+8UL) <= N; j+=8UL ) + { + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend( ( IsUpper::value ) + ?( IsStrictlyUpper::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 // Type of the scalar value + static inline DisableIf_< UseBlasKernel > + 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 > + selectBlasSubAssignKernel( VT1& y, const VT2& x, const MT1& A, ST2 scalar ) + { + typedef ElementType_ ET; + + if( IsTriangular::value ) { + ResultType_ tmp( serial( scalar * x ) ); + trmv( tmp, A, ( IsLower::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& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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 > + smpSubAssign( DenseVector& lhs, const DVecScalarMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + LeftOperand_ left ( rhs.vector_.leftOperand() ); + RightOperand_ 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 x, y; + blaze::DynamicMatrix 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, TDVecTDMatMultExpr > + operator*( const DenseVector& vec, const DenseMatrix& mat ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~vec).size() != (~mat).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" ); + } + + return TDVecTDMatMultExpr( ~vec, ~mat ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT > +struct Size< TDVecTDMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT > +struct IsAligned< TDVecTDMatMultExpr > + : public BoolConstant< And< IsAligned, IsAligned >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, bool AF > +struct SubvectorExprTrait< TDVecTDMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private TVecMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ VRT; //!< Result type of the left-hand side dense vector expression. + typedef ResultType_ MRT; //!< Result type of the right-hand side sparse matrix expression. + typedef CompositeType_ VCT; //!< Composite type of the left-hand side dense vector expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side sparse matrix expression. + enum : bool { evaluateMatrix = RequiresEvaluation::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 This; //!< Type of this TDVecTSMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT, const VT& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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 > + assign( DenseVector& 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 > + assign( SparseVector& 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_ ); + + 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 > + addAssign( DenseVector& 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 > + subAssign( DenseVector& 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 > + multAssign( DenseVector& 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_ ); + + 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 > + divAssign( DenseVector& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 x, y; + blaze::CompressedMatrix 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, TDVecTSMatMultExpr > + operator*( const DenseVector& vec, const SparseMatrix& mat ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~vec).size() != (~mat).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" ); + } + + return TDVecTSMatMultExpr( ~vec, ~mat ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT > +struct Size< TDVecTSMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT > +struct IsAligned< TDVecTSMatMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, bool AF > +struct SubvectorExprTrait< TDVecTSMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::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::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::value && + !IsResizable< ElementType_ >::value && + !IsResizable::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::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef TSMatDMatMultExpr This; //!< Type of this TSMatDMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side dense matrix expression. + typedef If_< IsExpression, 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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 > + assign( DenseMatrix& 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::value && size < TSMATDMATMULT_THRESHOLD ) || + ( IsColumnMajorMatrix::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_ ConstIterator; + + reset( C ); + + if( IsDiagonal::value ) + { + for( size_t i=0UL; iindex(),i) = element->value() * B(i,i); + } + } + } + else + { + const size_t block( IsRowMajorMatrix::value ? 256UL : 8UL ); + + for( size_t jj=0UL; jj B.columns() )?( B.columns() ):( jj+block ) ); + + for( size_t i=0UL; i::value ) + ?( max( IsStrictlyUpper::value ? i+1UL : i, jj ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( IsStrictlyLower::value ? i : i+1UL, jpos ) ) + :( jpos ) ); + + if( jbegin >= jend ) + continue; + + for( ; element!=end; ++element ) { + for( size_t j=jbegin; jindex(),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 > + 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 > + selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( ( IsRowMajorMatrix::value )?( 256UL ):( 8UL ) ); + + reset( C ); + + for( size_t jj=0UL; jj B.columns() )?( B.columns() ):( jj+block ) ); + + for( size_t i=0UL; i::value ) + ?( max( IsStrictlyUpper::value ? i+1UL : i, jj ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( IsStrictlyLower::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; kindex() ); + 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; jindex(),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 > + 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 > + selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_ ); + + const OppositeType_ 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 > + assign( SparseMatrix& 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_ ); + + 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 > + assign( Matrix& 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 > + addAssign( DenseMatrix& 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::value && size < TSMATDMATMULT_THRESHOLD ) || + ( IsColumnMajorMatrix::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_ ConstIterator; + + if( IsDiagonal::value ) + { + for( size_t i=0UL; iindex(),i) += element->value() * B(i,i); + } + } + } + else + { + const size_t block( IsRowMajorMatrix::value ? 256UL : 8UL ); + + for( size_t jj=0UL; jj B.columns() )?( B.columns() ):( jj+block ) ); + + for( size_t i=0UL; i::value ) + ?( max( IsStrictlyUpper::value ? i+1UL : i, jj ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( IsStrictlyLower::value ? i : i+1UL, jpos ) ) + :( jpos ) ); + + if( jbegin >= jend ) + continue; + + for( ; element!=end; ++element ) { + for( size_t j=jbegin; jindex(),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 > + 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 > + selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( ( IsRowMajorMatrix::value )?( 256UL ):( 8UL ) ); + + for( size_t jj=0UL; jj B.columns() )?( B.columns() ):( jj+block ) ); + + for( size_t i=0UL; i::value ) + ?( max( IsStrictlyUpper::value ? i+1UL : i, jj ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( IsStrictlyLower::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; kindex() ); + 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; jindex(),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 > + 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 > + selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_ ); + + const OppositeType_ 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 > + addAssign( Matrix& 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 > + subAssign( DenseMatrix& 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::value && size < TSMATDMATMULT_THRESHOLD ) || + ( IsColumnMajorMatrix::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_ ConstIterator; + + if( IsDiagonal::value ) + { + for( size_t i=0UL; iindex(),i) -= element->value() * B(i,i); + } + } + } + else + { + const size_t block( IsRowMajorMatrix::value ? 256UL : 8UL ); + + for( size_t jj=0UL; jj B.columns() )?( B.columns() ):( jj+block ) ); + + for( size_t i=0UL; i::value ) + ?( max( IsStrictlyUpper::value ? i+1UL : i, jj ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( IsStrictlyLower::value ? i : i+1UL, jpos ) ) + :( jpos ) ); + + if( jbegin >= jend ) + continue; + + for( ; element!=end; ++element ) { + for( size_t j=jbegin; jindex(),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 > + 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 > + selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( ( IsRowMajorMatrix::value )?( 256UL ):( 8UL ) ); + + for( size_t jj=0UL; jj B.columns() )?( B.columns() ):( jj+block ) ); + + for( size_t i=0UL; i::value ) + ?( max( IsStrictlyUpper::value ? i+1UL : i, jj ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( IsStrictlyLower::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; kindex() ); + 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; jindex(),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 > + 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 > + selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_ ); + + const OppositeType_ 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 > + subAssign( Matrix& 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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAssign( Matrix& 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 > + smpAddAssign( DenseMatrix& 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 > + smpAddAssign( Matrix& 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 > + smpSubAssign( DenseMatrix& 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 > + smpSubAssign( Matrix& 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 A; + blaze::DynamicMatrix B; + blaze::DynamicMatrix 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 + operator*( const SparseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TSMatDMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< TSMatDMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< TSMatDMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsAligned< TSMatDMatMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< TSMatDMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< TSMatDMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< TSMatDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< TSMatDMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< TSMatDMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< TSMatDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TDMatDVecMultExprTrait< TSMatDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseVector, IsColumnVector > + , TSMatDVecMultExprTrait_< MT1, DMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TDMatSVecMultExprTrait< TSMatDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsSparseVector, IsColumnVector > + , TSMatDVecMultExprTrait_< MT1, DMatSVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecTDMatMultExprTrait< VT, TSMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , TDVecDMatMultExprTrait_< TDVecTSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecTDMatMultExprTrait< VT, TSMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , TDVecDMatMultExprTrait_< TDVecTSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< TSMatDMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< TSMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< TSMatDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse matrix expression. + typedef ReturnType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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 This; //!< Type of this TSMatDMatSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::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& 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& 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_ ); + + 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& 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& 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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A; + blaze::DynamicMatrix 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 + operator-( const SparseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TSMatDMatSubExpr( ~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, T3 > + operator+( const TSMatDMatSubExpr& lhs, const DenseMatrix& 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, T3 > + operator-( const TSMatDMatSubExpr& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + return lhs.leftOperand() - ( lhs.rightOperand() + (~rhs) ); +} +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< TSMatDMatSubExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< TSMatDMatSubExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< TSMatDMatSubExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< TSMatDMatSubExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< TSMatDMatSubExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< TSMatDMatSubExpr > + : public BoolConstant< And< IsUniLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< TSMatDMatSubExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< TSMatDMatSubExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< TSMatDMatSubExpr > + : public BoolConstant< And< IsUniUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< TSMatDMatSubExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatAddExprTrait< TSMatDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatTSMatAddExprTrait_< DMatDMatSubExprTrait_, MT1 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatAddExprTrait< TSMatDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , DMatTSMatAddExprTrait_< TDMatDMatSubExprTrait_, MT1 > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatDMatSubExprTrait< TSMatDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , TSMatDMatSubExprTrait_< MT1, DMatDMatAddExprTrait_ > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename MT3 > +struct DMatTDMatSubExprTrait< TSMatDMatSubExpr, MT3 > +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TSMatDMatSubExprTrait_< MT1, DMatTDMatAddExprTrait_ > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< TSMatDMatSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< TSMatDMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< TSMatDMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ MRT; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ VRT; //!< Result type of the right-hand side dense vector expression. + typedef CompositeType_ MCT; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense vector expression. + enum : bool { evaluateVector = IsComputation::value || RequiresEvaluation::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 This; //!< Type of this TSMatDVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT, const MT& > LeftOperand; + + //! Composite type of the right-hand side dense vector expression. + typedef If_< IsExpression, 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::value ) + { + return mat_(index,index) * vec_[index]; + } + else if( IsLower::value ) + { + const size_t n( IsStrictlyLower::value ? index : index+1UL ); + return subvector( row( mat_, index ), 0UL, n ) * subvector( vec_, 0UL, n ); + } + else if( IsUpper::value ) + { + const size_t begin( IsStrictlyUpper::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& 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_ > ConstIterator; + + for( size_t j=0UL; j >::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& 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_ ); + + 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& 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_ > ConstIterator; + + for( size_t j=0UL; jindex()] += 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& 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_ > ConstIterator; + + for( size_t j=0UL; jindex()] -= 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& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 A; + blaze::DynamicVector 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, IsMatMatMultExpr >, TSMatDVecMultExpr > + operator*( const SparseMatrix& mat, const DenseVector& vec ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~mat).columns() != (~vec).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" ); + } + + return TSMatDVecMultExpr( ~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, MultExprTrait_ > + operator*( const SparseMatrix& mat, const DenseVector& 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 > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT > +struct IsAligned< TSMatDVecMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, bool AF > +struct SubvectorExprTrait< TSMatDVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side sparse matrix expression. + enum : bool { evaluateRight = RequiresEvaluation::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::value && IsSymmetric::value ) || + ( IsColumnMajorMatrix::value && IsSymmetric::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::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef TSMatSMatMultExpr This; //!< Type of this TSMatSMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 > + assign( DenseMatrix& 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_ LeftIterator; + typedef ConstIterator_ RightIterator; + + for( size_t j=0UL; j >::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 > + assign( SparseMatrix& 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_ ); + + const OppositeType_ 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 > + assign( SparseMatrix& 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_ ); + + const OppositeType_ 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 > + assign( Matrix& 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 > + assign( Matrix& 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 > + addAssign( DenseMatrix& 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_ LeftIterator; + typedef ConstIterator_ RightIterator; + + for( size_t j=0UL; jindex(),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 > + addAssign( Matrix& 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 > + addAssign( Matrix& 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& 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_ LeftIterator; + typedef ConstIterator_ RightIterator; + + for( size_t j=0UL; jindex(),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 > + subAssign( Matrix& 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 > + subAssign( Matrix& 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 > + smpAssign( Matrix& 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 > + smpAssign( Matrix& 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 > + smpAssign( Matrix& 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 > + smpAddAssign( DenseMatrix& 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 > + smpAddAssign( Matrix& 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 > + smpAddAssign( Matrix& 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 > + smpSubAssign( DenseMatrix& 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 > + smpSubAssign( Matrix& 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 > + smpSubAssign( Matrix& 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 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 + operator*( const SparseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TSMatSMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< TSMatSMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< TSMatSMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< TSMatSMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< TSMatSMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< TSMatSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< TSMatSMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< TSMatSMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< TSMatSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TSMatDVecMultExprTrait< TSMatSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsDenseVector, IsColumnVector > + , TSMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TSMatSVecMultExprTrait< TSMatSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix + , IsSparseVector, IsColumnVector > + , TSMatDVecMultExprTrait_< MT1, SMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecTSMatMultExprTrait< VT, TSMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , TDVecSMatMultExprTrait_< TDVecTSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecTSMatMultExprTrait< VT, TSMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , TDVecSMatMultExprTrait_< TDVecTSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< TSMatSMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< TSMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< TSMatSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatMatSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse matrix expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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::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 This; //!< Type of this TSMatSMatSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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& 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_ > RightIterator; + + assign( ~lhs, rhs.lhs_ ); + + if( !IsResizable< ElementType_ >::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 > + assign( SparseMatrix& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > RightIterator; + + // Evaluation of the left-hand side sparse matrix operand + const OppositeType_ 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 > + assign( SparseMatrix& 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 > + assign( SparseMatrix& 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_ > LeftIterator; + typedef ConstIterator_< OppositeType_ > 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_ 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 > + assign( SparseMatrix& 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& 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& 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 A; + blaze::CompressedMatrix 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 + operator-( const SparseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TSMatSMatSubExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< TSMatSMatSubExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< TSMatSMatSubExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< TSMatSMatSubExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< TSMatSMatSubExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< TSMatSMatSubExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< TSMatSMatSubExpr > + : public BoolConstant< And< IsUniLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< TSMatSMatSubExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< TSMatSMatSubExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< TSMatSMatSubExpr > + : public BoolConstant< And< IsUniUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< TSMatSMatSubExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< TSMatSMatSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< TSMatSMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< TSMatSMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, false > + , private MatVecMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ MRT; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ VRT; //!< Result type of the right-hand side sparse vector expression. + typedef CompositeType_ MCT; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side sparse vector expression. + enum : bool { evaluateVector = RequiresEvaluation::value || IsComputation::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 This; //!< Type of this TSMatSVecMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT, const MT& > LeftOperand; + + //! Composite type of the right-hand side sparse vector expression. + typedef If_< IsExpression, 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::value ) + { + return mat_(index,index) * vec_[index]; + } + else if( IsLower::value ) + { + const size_t n( IsStrictlyLower::value ? index : index+1UL ); + return subvector( row( mat_, index ), 0UL, n ) * subvector( vec_, 0UL, n ); + } + else if( IsUpper::value ) + { + const size_t begin( IsStrictlyUpper::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& 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_ > MatrixIterator; + typedef ConstIterator_< RemoveReference_ > 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_ >::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& lhs, const TSMatSVecMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + const DynamicVector,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& 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_ > MatrixIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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_ > MatrixIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 A; + blaze::CompressedVector 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, TSMatSVecMultExpr > + operator*( const SparseMatrix& mat, const SparseVector& vec ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~mat).columns() != (~vec).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix and vector sizes do not match" ); + } + + return TSMatSVecMultExpr( ~mat, ~vec ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SIZE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT > +struct Size< TSMatSVecMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, typename VT, bool AF > +struct SubvectorExprTrait< TSMatSVecMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubvectorExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ ET1; //!< Element type of the left-hand side dense matrix expression. + typedef ElementType_ ET2; //!< Element type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateRight = IsComputation::value || RequiresEvaluation::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::value || IsSymmetric::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::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::value && + !IsResizable< ElementType_ >::value && + !IsResizable::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::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef TSMatTDMatMultExpr This; //!< Type of this TSMatTDMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side dense matrix expression. + typedef If_< IsExpression, 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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 > + assign( DenseMatrix& 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::value && size < TSMATTDMATMULT_THRESHOLD ) || + ( IsColumnMajorMatrix::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_ ConstIterator; + + reset( C ); + + if( IsDiagonal::value ) + { + for( size_t i=0UL; iindex(),i) = element->value() * B(i,i); + } + } + } + else + { + const size_t block( 64UL ); + + for( size_t jj=0UL; jj B.columns() )?( B.columns() ):( jj+block ) ); + + for( size_t i=0UL; i::value ) + ?( max( IsStrictlyUpper::value ? i+1UL : i, jj ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( IsStrictlyLower::value ? i : i+1UL, jpos ) ) + :( jpos ) ); + + if( jbegin >= jend ) + continue; + + for( ; element!=end; ++element ) { + for( size_t j=jbegin; jindex(),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 > + 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 > + selectSmallAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsRowMajorMatrix::value ? 128UL : 64UL ); + + for( size_t jj=0UL; jj B.columns() )?( B.columns() ):( jj+block ) ); + + for( size_t i=0UL; i::value ) + ?( max( IsStrictlyUpper::value ? i+1UL : i, jj ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( IsStrictlyLower::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; kindex() ); + 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; jindex(),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 > + 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 > + selectLargeAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_ ); + + const OppositeType_ 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 > + assign( SparseMatrix& 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_ ); + + 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 > + assign( Matrix& 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::value && IsSymmetric::value ) + assign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + addAssign( DenseMatrix& 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::value && size < TSMATTDMATMULT_THRESHOLD ) || + ( IsColumnMajorMatrix::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_ ConstIterator; + + if( IsDiagonal::value ) + { + for( size_t i=0UL; iindex(),i) += element->value() * B(i,i); + } + } + } + else + { + const size_t block( 64UL ); + + for( size_t jj=0UL; jj B.columns() )?( B.columns() ):( jj+block ) ); + + for( size_t i=0UL; i::value ) + ?( max( IsStrictlyUpper::value ? i+1UL : i, jj ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( IsStrictlyLower::value ? i : i+1UL, jpos ) ) + :( jpos ) ); + + if( jbegin >= jend ) + continue; + + for( ; element!=end; ++element ) { + for( size_t j=jbegin; jindex(),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 > + 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 > + selectSmallAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsRowMajorMatrix::value ? 128UL : 64UL ); + + for( size_t jj=0UL; jj B.columns() )?( B.columns() ):( jj+block ) ); + + for( size_t i=0UL; i::value ) + ?( max( IsStrictlyUpper::value ? i+1UL : i, jj ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( IsStrictlyLower::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; kindex() ); + 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; jindex(),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 > + 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 > + selectLargeAddAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_ ); + + const OppositeType_ 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 > + addAssign( Matrix& 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::value && IsSymmetric::value ) + addAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + subAssign( DenseMatrix& 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::value && size < TSMATTDMATMULT_THRESHOLD ) || + ( IsColumnMajorMatrix::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_ ConstIterator; + + if( IsDiagonal::value ) + { + for( size_t i=0UL; iindex(),i) -= element->value() * B(i,i); + } + } + } + else + { + const size_t block( 64UL ); + + for( size_t jj=0UL; jj B.columns() )?( B.columns() ):( jj+block ) ); + + for( size_t i=0UL; i::value ) + ?( max( IsStrictlyUpper::value ? i+1UL : i, jj ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( IsStrictlyLower::value ? i : i+1UL, jpos ) ) + :( jpos ) ); + + if( jbegin >= jend ) + continue; + + for( ; element!=end; ++element ) { + for( size_t j=jbegin; jindex(),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 > + 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 > + selectSmallSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + typedef ConstIterator_ ConstIterator; + + const size_t block( IsRowMajorMatrix::value ? 128UL : 64UL ); + + for( size_t jj=0UL; jj B.columns() )?( B.columns() ):( jj+block ) ); + + for( size_t i=0UL; i::value ) + ?( max( IsStrictlyUpper::value ? i+1UL : i, jj ) ) + :( jj ) ); + const size_t jend( ( IsLower::value ) + ?( min( IsStrictlyLower::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; kindex() ); + 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; jindex(),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 > + 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 > + selectLargeSubAssignKernel( MT3& C, const MT4& A, const MT5& B ) + { + BLAZE_CONSTRAINT_MUST_BE_ROW_MAJOR_MATRIX_TYPE( OppositeType_ ); + + const OppositeType_ 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 > + subAssign( Matrix& 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::value && IsSymmetric::value ) + subAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + smpAssign( DenseMatrix& 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 > + smpAssign( SparseMatrix& 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_ ); + + 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 > + smpAssign( Matrix& 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::value && IsSymmetric::value ) + smpAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + smpAddAssign( DenseMatrix& 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 > + smpAddAssign( Matrix& 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::value && IsSymmetric::value ) + smpAddAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 > + smpSubAssign( DenseMatrix& 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 > + smpSubAssign( Matrix& 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::value && IsSymmetric::value ) + smpSubAssign( ~lhs, trans( rhs.lhs_ ) * trans( rhs.rhs_ ) ); + else if( IsSymmetric::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 A; + blaze::DynamicMatrix 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 + operator*( const SparseMatrix& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TSMatTDMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< TSMatTDMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< TSMatTDMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsAligned< TSMatTDMatMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< TSMatTDMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< TSMatTDMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< TSMatTDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< TSMatTDMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< TSMatTDMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< TSMatTDMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TDMatDVecMultExprTrait< TSMatTDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector > + , TSMatDVecMultExprTrait_< MT1, TDMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TDMatSVecMultExprTrait< TSMatTDMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector > + , TSMatDVecMultExprTrait_< MT1, TDMatSVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecTDMatMultExprTrait< VT, TSMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDVecTDMatMultExprTrait_< TDVecTSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecTDMatMultExprTrait< VT, TSMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TSVecTDMatMultExprTrait_< TSVecTSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< TSMatTDMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< TSMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< TSMatTDMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private MatMatAddExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse matrix expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef AddExprTrait_ 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::value && IsSymmetric::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 This; //!< Type of this TSMatTSMatAddExpr instance. + typedef AddTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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& 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_ > RightIterator; + + assign( ~lhs, rhs.lhs_ ); + + if( !IsResizable< ElementType_ >::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 > + assign( SparseMatrix& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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 nonzeros( m, 0UL ); + for( size_t j=0UL; jindex() < 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; iindex() < 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 > + assign( SparseMatrix& 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& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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& 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 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 + operator+( const SparseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TSMatTSMatAddExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< TSMatTSMatAddExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< TSMatTSMatAddExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< TSMatTSMatAddExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< TSMatTSMatAddExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< TSMatTSMatAddExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< TSMatTSMatAddExpr > + : public BoolConstant< Or< And< IsUniLower, IsStrictlyLower > + , And< IsUniLower, IsStrictlyLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< TSMatTSMatAddExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< TSMatTSMatAddExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< TSMatTSMatAddExpr > + : public BoolConstant< Or< And< IsUniUpper, IsStrictlyUpper > + , And< IsUniUpper, IsStrictlyUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< TSMatTSMatAddExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< TSMatTSMatAddExpr, AF > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< TSMatTSMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< TSMatTSMatAddExpr > +{ + public: + //********************************************************************************************** + using Type = AddExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private MatMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side sparse matrix expression. + enum : bool { evaluateRight = RequiresEvaluation::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::value && + IsSymmetric::value && IsSymmetric::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::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef TSMatTSMatMultExpr This; //!< Type of this TSMatTSMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::value ) { + return lhs_(i,i) * rhs_(i,j); + } + else if( IsDiagonal::value ) { + return lhs_(i,j) * rhs_(j,j); + } + else if( IsTriangular::value || IsTriangular::value ) { + const size_t begin( ( IsUpper::value ) + ?( ( IsLower::value ) + ?( max( ( IsStrictlyUpper::value ? i+1UL : i ) + , ( IsStrictlyLower::value ? j+1UL : j ) ) ) + :( IsStrictlyUpper::value ? i+1UL : i ) ) + :( ( IsLower::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ) ); + const size_t end( ( IsLower::value ) + ?( ( IsUpper::value ) + ?( min( ( IsStrictlyLower::value ? i : i+1UL ) + , ( IsStrictlyUpper::value ? j : j+1UL ) ) ) + :( IsStrictlyLower::value ? i : i+1UL ) ) + :( ( IsUpper::value ) + ?( IsStrictlyUpper::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 > + assign( DenseMatrix& 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_ LeftIterator; + typedef ConstIterator_ RightIterator; + + for( size_t j=0UL; jindex() ) ); + for( LeftIterator lelem=A.begin( relem->index() ); lelem!=lend; ++lelem ) + { + if( IsResizable< ElementType_ >::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 > + assign( SparseMatrix& 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& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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 values ( (~lhs).rows(), ElementType() ); + std::vector valid ( (~lhs).rows(), 0 ); + std::vector 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 // Type of the target matrix + friend inline EnableIf_< CanExploitSymmetry > + assign( Matrix& 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 > + addAssign( DenseMatrix& 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_ LeftIterator; + typedef ConstIterator_ RightIterator; + + for( size_t j=0UL; jindex() ) ); + 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 > + addAssign( Matrix& 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 > + subAssign( DenseMatrix& 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_ LeftIterator; + typedef ConstIterator_ RightIterator; + + for( size_t j=0UL; jindex() ) ); + 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 > + subAssign( Matrix& 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 > + smpAssign( Matrix& 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 > + smpAssign( Matrix& 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 > + smpAddAssign( DenseMatrix& 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 > + smpAddAssign( Matrix& 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 > + smpSubAssign( DenseMatrix& 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 > + smpSubAssign( Matrix& 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 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 + operator*( const SparseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).columns() != (~rhs).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TSMatTSMatMultExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< TSMatTSMatMultExpr > : public Rows +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< TSMatTSMatMultExpr > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< TSMatTSMatMultExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< TSMatTSMatMultExpr > + : public BoolConstant< And< IsUniLower, IsUniLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< TSMatTSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyLower, IsLower > + , And< IsStrictlyLower, IsLower > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< TSMatTSMatMultExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< TSMatTSMatMultExpr > + : public BoolConstant< And< IsUniUpper, IsUniUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< TSMatTSMatMultExpr > + : public BoolConstant< Or< And< IsStrictlyUpper, IsUpper > + , And< IsStrictlyUpper, IsUpper > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TSMatDVecMultExprTrait< TSMatTSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector > + , TSMatDVecMultExprTrait_< MT1, TSMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, typename VT > +struct TSMatSVecMultExprTrait< TSMatTSMatMultExpr, VT > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector > + , TSMatDVecMultExprTrait_< MT1, TSMatDVecMultExprTrait_ > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TDVecTSMatMultExprTrait< VT, TSMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsDenseVector, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , TDVecTSMatMultExprTrait_< TDVecTSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT1, typename MT2 > +struct TSVecTSMatMultExprTrait< VT, TSMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = If_< And< IsSparseVector, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , TSVecTSMatMultExprTrait_< TSVecTSMatMultExprTrait_, MT2 > + , INVALID_TYPE >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< TSMatTSMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< TSMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< RowExprTrait_, MT2 >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< TSMatTSMatMultExpr > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< MT1, ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private MatMatSubExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ RT1; //!< Result type of the left-hand side sparse matrix expression. + typedef ResultType_ RT2; //!< Result type of the right-hand side sparse matrix expression. + typedef ReturnType_ RN1; //!< Return type of the left-hand side sparse matrix expression. + typedef ReturnType_ RN2; //!< Return type of the right-hand side sparse matrix expression. + typedef CompositeType_ CT1; //!< Composite type of the left-hand side sparse matrix expression. + typedef CompositeType_ 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::value && !IsTemporary::value }; + + //! Expression return type for the subscript operator. + typedef SubExprTrait_ 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::value && IsSymmetric::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 This; //!< Type of this TSMatTSMatSubExpr instance. + typedef SubTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const MT1, const MT1& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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& 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_ > RightIterator; + + assign( ~lhs, rhs.lhs_ ); + + if( !IsResizable< ElementType_ >::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 > + assign( SparseMatrix& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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 nonzeros( m, 0UL ); + for( size_t j=0UL; jindex() < 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; iindex() < 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 > + assign( SparseMatrix& 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& 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_ > LeftIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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& 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 > + smpAddAssign( DenseMatrix& 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 > + smpSubAssign( DenseMatrix& 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 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 + operator-( const SparseMatrix& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~lhs).rows() != (~rhs).rows() || (~lhs).columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + return TSMatTSMatSubExpr( ~lhs, ~rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Rows< TSMatTSMatSubExpr > + : public Max< Rows, Rows > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct Columns< TSMatTSMatSubExpr > + : public Max< Columns, Columns > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSYMMETRIC SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsSymmetric< TSMatTSMatSubExpr > + : public BoolConstant< IsSymmetric::value && IsSymmetric::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISHERMITIAN SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsHermitian< TSMatTSMatSubExpr > + : public BoolConstant< IsHermitian::value && IsHermitian::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsLower< TSMatTSMatSubExpr > + : public BoolConstant< And< IsLower, IsLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNILOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniLower< TSMatTSMatSubExpr > + : public BoolConstant< And< IsUniLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYLOWER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyLower< TSMatTSMatSubExpr > + : public BoolConstant< And< IsStrictlyLower, IsStrictlyLower >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUpper< TSMatTSMatSubExpr > + : public BoolConstant< And< IsUpper, IsUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISUNIUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsUniUpper< TSMatTSMatSubExpr > + : public BoolConstant< And< IsUniUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISSTRICTLYUPPER SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct IsStrictlyUpper< TSMatTSMatSubExpr > + : public BoolConstant< And< IsStrictlyUpper, IsStrictlyUpper >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2, bool AF > +struct SubmatrixExprTrait< TSMatTSMatSubExpr, AF > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< SubmatrixExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct RowExprTrait< TSMatTSMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< RowExprTrait_ + , RowExprTrait_ >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT1, typename MT2 > +struct ColumnExprTrait< TSMatTSMatSubExpr > +{ + public: + //********************************************************************************************** + using Type = SubExprTrait_< ColumnExprTrait_ + , ColumnExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private TVecMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ VRT; //!< Result type of the left-hand side sparse vector expression. + typedef ResultType_ MRT; //!< Result type of the right-hand side dense matrix expression. + typedef ElementType_ VET; //!< Element type of the left-hand side sparse vector expression. + typedef ElementType_ MET; //!< Element type of the right-hand side dense matrix expression. + typedef CompositeType_ VCT; //!< Composite type of the left-hand side sparse vector expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateMatrix = RequiresEvaluation::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::value && + T1::simdEnabled && T3::simdEnabled && + AreSIMDCombinable< ElementType_ + , ElementType_ + , ElementType_ >::value && + HasSIMDAdd< ElementType_, ElementType_ >::value && + HasSIMDMult< ElementType_, ElementType_ >::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::value && + !IsDiagonal::value && + !IsResizable< ElementType_ >::value && + !IsResizable::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::value && + !UseOptimizedKernel::value }; + }; + /*! \endcond */ + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef TSVecDMatMultExpr This; //!< Type of this TSVecDMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Resulting element type. + typedef SIMDTrait_ 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, const VT, const VT& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::value && + MT::simdEnabled && + HasSIMDAdd::value && + HasSIMDMult::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::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::value ) + { + return vec_[index] * mat_(index,index); + } + else if( IsLower::value ) + { + const size_t begin( IsStrictlyLower::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::value ) + { + const size_t n( IsStrictlyUpper::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& 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 > + selectAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ConstIterator_< RemoveReference_ > 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::value ) { + const size_t jend( IsStrictlyUpper::value ? element->index()+1UL : element->index() ); + for( size_t j=0UL; jindex() ); + + if( IsDiagonal::value ) + { + + + for( size_t j=last; jvalue() * A(index,index); + last = index + 1UL; + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? index+1UL : index ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? index : index+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; jvalue() * A(index,j); + } + for( size_t j=last; jvalue() * A(index,j); + } + + last = jend; + } + } + + if( IsLower::value ) { + for( size_t j=last; j // Type of the right-hand side matrix operand + static inline EnableIf_< UseOptimizedKernel > + selectAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ConstIterator_< RemoveReference_ > 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; jindex() ); + const VET v1( element->value() ); + ++element; + + for( size_t j=0UL; j3UL)?(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::value ) + ?( IsStrictlyUpper::value ? i1+1UL : i1 ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i4 : i4+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; jindex() ); + const VET v1( element->value() ); + + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i1+1UL : i1 ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i1 : i1+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedKernel > + selectAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" ); + + const size_t N( A.columns() ); + + const bool remainder( !IsPadded::value || !IsPadded::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( ; jindex() ); + 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( ; j3UL)?(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::value ) + ?( ( IsStrictlyUpper::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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( ; jindex() ); + const VET v1( element->value() ); + + const SIMDType xmm1( set( v1 ) ); + + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the target sparse vector + friend inline void assign( SparseVector& 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_ ); + + 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& 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 > + selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ConstIterator_< RemoveReference_ > 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::value ) + { + y[index] += A(index,index) * element->value(); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? index+1UL : index ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? index : index+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; jvalue() * 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 > + selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ConstIterator_< RemoveReference_ > 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i1 ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i4 : i4+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; jindex() ); + const VET v1( element->value() ); + + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i1+1UL : i1 ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i1 : i1+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedKernel > + selectAddAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" ); + + const size_t N( A.columns() ); + + const bool remainder( !IsPadded::value || !IsPadded::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::value ) + ?( ( IsStrictlyUpper::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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( ; jindex() ); + const VET v1( element->value() ); + + const SIMDType xmm1( set( v1 ) ); + + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the target dense vector + friend inline void subAssign( DenseVector& 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 > + selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ConstIterator_< RemoveReference_ > 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::value ) + { + y[index] -= A(index,index) * element->value(); + } + else + { + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? index+1UL : index ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? index : index+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; jvalue() * 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 > + selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ConstIterator_< RemoveReference_ > 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i1 ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i4 : i4+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; jindex() ); + const VET v1( element->value() ); + + const size_t jbegin( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? i1+1UL : i1 ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::value ? i1 : i1+1UL ) + :( N ) ); + BLAZE_INTERNAL_ASSERT( jbegin <= jend, "Invalid loop indices detected" ); + + for( size_t j=jbegin; j // Type of the right-hand side matrix operand + static inline EnableIf_< UseVectorizedKernel > + selectSubAssignKernel( VT1& y, const VT2& x, const MT1& A ) + { + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + BLAZE_INTERNAL_ASSERT( x.nonZeros() != 0UL, "Invalid number of non-zero elements" ); + + const size_t N( A.columns() ); + + const bool remainder( !IsPadded::value || !IsPadded::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::value ) + ?( ( IsStrictlyUpper::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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( ; jindex() ); + const VET v1( element->value() ); + + const SIMDType xmm1( set( v1 ) ); + + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ? i1+1UL : i1 ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend( ( IsLower::value ) + ?( IsStrictlyLower::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 // Type of the target dense vector + friend inline void multAssign( DenseVector& 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_ ); + + 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& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 x, y; + blaze::DynamicMatrix 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, TSVecDMatMultExpr > + operator*( const SparseVector& vec, const DenseMatrix& mat ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~vec).size() != (~mat).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" ); + } + + return TSVecDMatMultExpr( ~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, MultExprTrait_ > + operator*( const SparseVector& vec, const DenseMatrix& 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 > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT > +struct IsAligned< TSVecDMatMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, bool AF > +struct SubvectorExprTrait< TSVecDMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 a; + blaze::DynamicVector 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_, ElementType_ > + operator*( const SparseVector& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + typedef CompositeType_ Lhs; // Composite type of the left-hand side sparse vector expression + typedef CompositeType_ Rhs; // Composite type of the right-hand side dense vector expression + typedef RemoveReference_ X1; // Auxiliary type for the left-hand side composite type + typedef RemoveReference_ X2; // Auxiliary type for the right-hand side composite type + typedef ElementType_ ET1; // Element type of the left-hand side sparse vector expression + typedef ElementType_ ET2; // Element type of the right-hand side dense vector expression + typedef MultTrait_ MultType; // Multiplication result type + typedef ConstIterator_ 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private TVecMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ VRT; //!< Result type of the left-hand side sparse vector expression. + typedef ResultType_ MRT; //!< Result type of the right-hand side sparse matrix expression. + typedef CompositeType_ VCT; //!< Composite type of the left-hand side sparse vector expression. + typedef CompositeType_ 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::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side sparse matrix expression. + enum : bool { evaluateMatrix = RequiresEvaluation::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 This; //!< Type of this TSVecSMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT, const VT& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::value ) + { + return vec_[index] * mat_(index,index); + } + else if( IsLower::value ) + { + const size_t begin( IsStrictlyLower::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::value ) + { + const size_t n( IsStrictlyUpper::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& 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_ > VectorIterator; + typedef ConstIterator_< RemoveReference_ > 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_ >::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& lhs, const TSVecSMatMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + const DynamicVector,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& 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_ > VectorIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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_ > VectorIterator; + typedef ConstIterator_< RemoveReference_ > 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& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 x, y; + blaze::CompressedMatrix 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, TSVecSMatMultExpr > + operator*( const SparseVector& vec, const SparseMatrix& mat ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~vec).size() != (~mat).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" ); + } + + return TSVecSMatMultExpr( ~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, MultExprTrait_ > + operator*( const SparseVector& vec, const SparseMatrix& 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 > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, bool AF > +struct SubvectorExprTrait< TSVecSMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 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_, ElementType_ > + operator*( const SparseVector& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + typedef CompositeType_ Lhs; // Composite type of the left-hand side sparse vector expression + typedef CompositeType_ Rhs; // Composite type of the right-hand side sparse vector expression + typedef RemoveReference_ X1; // Auxiliary type for the left-hand side composite type + typedef RemoveReference_ X2; // Auxiliary type for the right-hand side composite type + typedef ElementType_ E1; // Element type of the left-hand side sparse vector expression + typedef ElementType_ E2; // Element type of the right-hand side sparse vector expression + typedef MultTrait_ MultType; // Multiplication result type + typedef ConstIterator_ LeftIterator; // Iterator type of the left-hand sparse vector expression + typedef ConstIterator_ 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::value && IsOpposedView::value ) + { + if( left.size() == 0UL ) return sp; + + sp = left[0UL] * right[0UL]; + for( size_t i=1UL; i::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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private TVecMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ VRT; //!< Result type of the left-hand side sparse vector expression. + typedef ResultType_ MRT; //!< Result type of the right-hand side dense matrix expression. + typedef CompositeType_ VCT; //!< Composite type of the left-hand side sparse vector expression. + typedef CompositeType_ 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::value || RequiresEvaluation::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side dense matrix expression. + enum : bool { evaluateMatrix = RequiresEvaluation::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 This; //!< Type of this TSVecTDMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT, const VT& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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::value ) + { + return vec_[index] * mat_(index,index); + } + else if( IsLower::value ) + { + const size_t begin( IsStrictlyLower::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::value ) + { + const size_t n( IsStrictlyUpper::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 > + assign( DenseVector& 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 > + assign( SparseVector& 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_ ); + + 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 > + addAssign( DenseVector& 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 > + subAssign( DenseVector& 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 > + multAssign( DenseVector& 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_ ); + + 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 > + divAssign( DenseVector& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAssign( SparseVector& 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_ ); + + 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 > + smpDivAssign( DenseVector& 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_ ); + + 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 x, y; + blaze::DynamicMatrix 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, IsMatMatMultExpr >, TSVecTDMatMultExpr > + operator*( const SparseVector& vec, const DenseMatrix& mat ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~vec).size() != (~mat).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" ); + } + + return TSVecTDMatMultExpr( ~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, MultExprTrait_ > + operator*( const SparseVector& vec, const DenseMatrix& 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 > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT > +struct IsAligned< TSVecTDMatMultExpr > + : public BoolConstant< IsAligned::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, bool AF > +struct SubvectorExprTrait< TSVecTDMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, true > + , private TVecMatMultExpr + , private Computation +{ + private: + //**Type definitions**************************************************************************** + typedef ResultType_ VRT; //!< Result type of the left-hand side sparse vector expression. + typedef ResultType_ MRT; //!< Result type of the right-hand side sparse matrix expression. + typedef CompositeType_ VCT; //!< Composite type of the left-hand side sparse vector expression. + typedef CompositeType_ 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::value }; + //********************************************************************************************** + + //********************************************************************************************** + //! Compilation switch for the composite type of the right-hand side sparse matrix expression. + enum : bool { evaluateMatrix = RequiresEvaluation::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 This; //!< Type of this TSVecTSMatMultExpr instance. + typedef MultTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ 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, const VT, const VT& > LeftOperand; + + //! Composite type of the right-hand side sparse matrix expression. + typedef If_< IsExpression, 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& 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_ > VectorIterator; + typedef ConstIterator_< RemoveReference_ > MatrixIterator; + + const VectorIterator vend( x.end() ); + + for( size_t j=0UL; jindex() < 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& lhs, const TSVecTSMatMultExpr& rhs ) + { + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( (~lhs).size() == rhs.size(), "Invalid vector sizes" ); + + typedef ConstIterator_< RemoveReference_ > VectorIterator; + typedef ConstIterator_< RemoveReference_ > 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; jindex() < 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& 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_ > VectorIterator; + typedef ConstIterator_< RemoveReference_ > MatrixIterator; + + const VectorIterator vend( x.end() ); + + for( size_t j=0UL; jindex() < 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& 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_ > VectorIterator; + typedef ConstIterator_< RemoveReference_ > MatrixIterator; + + const VectorIterator vend( x.end() ); + + for( size_t j=0UL; jindex() < 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& 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_ ); + + 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 > + smpAssign( DenseVector& 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 > + smpAddAssign( DenseVector& 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 > + smpSubAssign( DenseVector& 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 > + smpMultAssign( DenseVector& 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_ ); + + 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 x, y; + blaze::CompressedMatrix 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, IsMatMatMultExpr >, TSVecTSMatMultExpr > + operator*( const SparseVector& vec, const SparseMatrix& mat ) +{ + BLAZE_FUNCTION_TRACE; + + if( (~vec).size() != (~mat).rows() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector and matrix sizes do not match" ); + } + + return TSVecTSMatMultExpr( ~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, MultExprTrait_ > + operator*( const SparseVector& vec, const SparseMatrix& 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 > : public Columns +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// EXPRESSION TRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, typename MT, bool AF > +struct SubvectorExprTrait< TSVecTSMatMultExpr, AF > +{ + public: + //********************************************************************************************** + using Type = MultExprTrait_< SubvectorExprTrait_ + , SubmatrixExprTrait_ >; + //********************************************************************************************** +}; +/*! \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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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( 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( this ); + } + //********************************************************************************************** +}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Vector global functions */ +//@{ +template< typename VT, bool TF > +BLAZE_ALWAYS_INLINE typename VT::Iterator begin( Vector& vector ); + +template< typename VT, bool TF > +BLAZE_ALWAYS_INLINE typename VT::ConstIterator begin( const Vector& vector ); + +template< typename VT, bool TF > +BLAZE_ALWAYS_INLINE typename VT::ConstIterator cbegin( const Vector& vector ); + +template< typename VT, bool TF > +BLAZE_ALWAYS_INLINE typename VT::Iterator end( Vector& vector ); + +template< typename VT, bool TF > +BLAZE_ALWAYS_INLINE typename VT::ConstIterator end( const Vector& vector ); + +template< typename VT, bool TF > +BLAZE_ALWAYS_INLINE typename VT::ConstIterator cend( const Vector& vector ); + +template< typename VT, bool TF > +BLAZE_ALWAYS_INLINE size_t size( const Vector& vector ) noexcept; + +template< typename VT, bool TF > +BLAZE_ALWAYS_INLINE size_t capacity( const Vector& vector ) noexcept; + +template< typename VT, bool TF > +BLAZE_ALWAYS_INLINE size_t nonZeros( const Vector& vector ); + +template< typename VT, bool TF > +BLAZE_ALWAYS_INLINE void resize( Vector& vector, size_t n, bool preserve=true ); + +template< typename VT1, bool TF1, typename VT2, bool TF2 > +BLAZE_ALWAYS_INLINE bool isSame( const Vector& a, const Vector& 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& 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& 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& 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& 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& 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& 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& 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& 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& 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 > + resize_backend( Vector& 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 > + resize_backend( Vector& 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 a( 3UL ); + resize( a, 5UL ); // OK: regular resize operation + + blaze::StaticVector 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& 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 VectorType; + typedef blaze::Subvector 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& a, const Vector& b ) noexcept +{ + return ( IsSame::value && + reinterpret_cast( &a ) == reinterpret_cast( &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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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& 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 + + +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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 + + +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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 + + +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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include + + +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 +#include + + +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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ 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() ) ) + { + 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::value && HasSIMDPow::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() ) ) + { + 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 +#include + + +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 + + +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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 +#include +#include +#include +#include + + +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::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 + + +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 +#include + + +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* A, int lda, complex* tau, + complex* work, int lwork, int* info ); + +inline void gelqf( int m, int n, complex* A, int lda, complex* tau, + complex* 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 v(0:i-1) = 0 and +// v(i) = 1. v(i+1:n) is stored on exit in A(i,i+1:n), 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 v(0:i-1) = 0 and +// v(i) = 1. v(i+1:n) is stored on exit in A(i,i+1:n), 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 v(0:i-1) = 0 and +// v(i) = 1. v(i+1:n) is stored on exit in A(i,i+1:n), 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* A, int lda, complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cgelqf_( &m, &n, reinterpret_cast( A ), &lda, reinterpret_cast( tau ), + reinterpret_cast( 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 v(0:i-1) = 0 and +// v(i) = 1. v(i+1:n) is stored on exit in A(i,i+1:n), 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* A, int lda, complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zgelqf_( &m, &n, reinterpret_cast( A ), &lda, reinterpret_cast( tau ), + reinterpret_cast( 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 +#include + + +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* A, int lda, complex* tau, + complex* work, int lwork, int* info ); + +inline void geqlf( int m, int n, complex* A, int lda, complex* tau, + complex* 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 v(m-k+i+1:m) = 0 and +// v(m-k+i) = 1. v(1:m-k+i-1) is stored on exit in A(1:m-k+i-1,n-k+i), +// 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 v(m-k+i+1:m) = 0 and +// v(m-k+i) = 1. v(1:m-k+i-1) is stored on exit in A(1:m-k+i-1,n-k+i), +// 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 v(m-k+i+1:m) = 0 and +// v(m-k+i) = 1. v(1:m-k+i-1) is stored on exit in A(1:m-k+i-1,n-k+i), +// 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* A, int lda, complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cgeqlf_( &m, &n, reinterpret_cast( A ), &lda, reinterpret_cast( tau ), + reinterpret_cast( 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 v(m-k+i+1:m) = 0 and +// v(m-k+i) = 1. v(1:m-k+i-1) is stored on exit in A(1:m-k+i-1,n-k+i), +// 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* A, int lda, complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zgeqlf_( &m, &n, reinterpret_cast( A ), &lda, reinterpret_cast( tau ), + reinterpret_cast( 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 v(0:i-1) = 0 and +// v(i) = 1. v(i+1:m) is stored on exit in A(i+1:m,i), 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 v(0:i-1) = 0 and +// v(i) = 1. v(i+1:m) is stored on exit in A(i+1:m,i), 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 +#include + + +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* A, int lda, complex* tau, + complex* work, int lwork, int* info ); + +inline void geqrf( int m, int n, complex* A, int lda, complex* tau, + complex* 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 v(0:i-1) = 0 and +// v(i) = 1. v(i+1:m) is stored on exit in A(i+1:m,i), 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 v(0:i-1) = 0 and +// v(i) = 1. v(i+1:m) is stored on exit in A(i+1:m,i), 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 v(0:i-1) = 0 and +// v(i) = 1. v(i+1:m) is stored on exit in A(i+1:m,i), 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* A, int lda, complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cgeqrf_( &m, &n, reinterpret_cast( A ), &lda, reinterpret_cast( tau ), + reinterpret_cast( 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 v(0:i-1) = 0 and +// v(i) = 1. v(i+1:m) is stored on exit in A(i+1:m,i), 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* A, int lda, complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zgeqrf_( &m, &n, reinterpret_cast( A ), &lda, reinterpret_cast( tau ), + reinterpret_cast( 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 +#include + + +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* A, int lda, complex* tau, + complex* work, int lwork, int* info ); + +inline void gerqf( int m, int n, complex* A, int lda, complex* tau, + complex* 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 v(n-k+i+1:n) = 0 and +// v(n-k+i) = 1. v(1:n-k+i-1) is stored on exit in A(m-k+i,1:n-k+i-1), +// 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 v(n-k+i+1:n) = 0 and +// v(n-k+i) = 1. v(1:n-k+i-1) is stored on exit in A(m-k+i,1:n-k+i-1), +// 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 v(n-k+i+1:n) = 0 and +// v(n-k+i) = 1. v(1:n-k+i-1) is stored on exit in A(m-k+i,1:n-k+i-1), +// 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* A, int lda, complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cgerqf_( &m, &n, reinterpret_cast( A ), &lda, reinterpret_cast( tau ), + reinterpret_cast( 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 v(n-k+i+1:n) = 0 and +// v(n-k+i) = 1. v(1:n-k+i-1) is stored on exit in A(m-k+i,1:n-k+i-1), +// 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* A, int lda, complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zgerqf_( &m, &n, reinterpret_cast( A ), &lda, reinterpret_cast( tau ), + reinterpret_cast( 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 +#include + + +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* A, int lda, int* ipiv, complex* B, int ldb, int* info ); + +inline void gesv( int n, int nrhs, complex* A, int lda, int* ipiv, complex* 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* A, int lda, int* ipiv, complex* B, int ldb, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cgesv_( &n, &nrhs, reinterpret_cast( A ), &lda, ipiv, + reinterpret_cast( 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* A, int lda, int* ipiv, complex* B, int ldb, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zgesv_( &n, &nrhs, reinterpret_cast( A ), &lda, ipiv, + reinterpret_cast( 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 +#include + + +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* A, int lda, int* ipiv, int* info ); + +inline void getrf( int m, int n, complex* 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* A, int lda, int* ipiv, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cgetrf_( &m, &n, reinterpret_cast( 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* A, int lda, int* ipiv, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zgetrf_( &m, &n, reinterpret_cast( 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 +#include + + +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* A, int lda, const int* ipiv, + complex* work, int lwork, int* info ); + +inline void getri( int n, complex* A, int lda, const int* ipiv, + complex* 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( 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( 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* A, int lda, const int* ipiv, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cgetri_( &n, reinterpret_cast( A ), &lda, const_cast( ipiv ), + reinterpret_cast( 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* A, int lda, const int* ipiv, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zgetri_( &n, reinterpret_cast( A ), &lda, const_cast( ipiv ), + reinterpret_cast( 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 +#include + + +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* A, int lda, + const int* ipiv, complex* B, int ldb, int* info ); + +inline void getrs( char trans, int n, int nrhs, const complex* A, int lda, + const int* ipiv, complex* 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( A ), &lda, + const_cast( 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( A ), &lda, + const_cast( 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* A, int lda, + const int* ipiv, complex* B, int ldb, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cgetrs_( &trans, &n, &nrhs, const_cast( reinterpret_cast( A ) ), + &lda, const_cast( ipiv ), reinterpret_cast( 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* A, int lda, + const int* ipiv, complex* B, int ldb, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zgetrs_( &trans, &n, &nrhs, const_cast( reinterpret_cast( A ) ), + &lda, const_cast( ipiv ), reinterpret_cast( 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 +#include + + +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* A, int lda, int* ipiv, + complex* B, int ldb, complex* work, int lwork, int* info ); + +inline void hesv( char uplo, int n, int nrhs, complex* A, int lda, int* ipiv, + complex* B, int ldb, complex* 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* A, int lda, int* ipiv, + complex* B, int ldb, complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + chesv_( &uplo, &n, &nrhs, reinterpret_cast( A ), &lda, ipiv, + reinterpret_cast( B ), &ldb, reinterpret_cast( 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* A, int lda, int* ipiv, + complex* B, int ldb, complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zhesv_( &uplo, &n, &nrhs, reinterpret_cast( A ), &lda, ipiv, + reinterpret_cast( B ), &ldb, reinterpret_cast( 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 +#include + + +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* A, int lda, int* ipiv, + complex* work, int lwork, int* info ); + +inline void hetrf( char uplo, int n, complex* A, int lda, int* ipiv, + complex* 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* A, int lda, int* ipiv, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + chetrf_( &uplo, &n, reinterpret_cast( A ), &lda, ipiv, + reinterpret_cast( 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* A, int lda, int* ipiv, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zhetrf_( &uplo, &n, reinterpret_cast( A ), &lda, ipiv, + reinterpret_cast( 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 +#include + + +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* A, int lda, + const int* ipiv, complex* work, int* info ); + +inline void hetri( char uplo, int n, complex* A, int lda, + const int* ipiv, complex* 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* A, int lda, + const int* ipiv, complex* work, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + chetri_( &uplo, &n, reinterpret_cast( A ), &lda, + const_cast( ipiv ), reinterpret_cast( 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* A, int lda, + const int* ipiv, complex* work, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zhetri_( &uplo, &n, reinterpret_cast( A ), &lda, + const_cast( ipiv ), reinterpret_cast( 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 +#include + + +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* A, int lda, const int* ipiv, + complex* B, int ldb, int* info ); + +inline void hetrs( char uplo, int n, int nrhs, const complex* A, int lda, const int* ipiv, + complex* 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* A, int lda, + const int* ipiv, complex* B, int ldb, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + chetrs_( &uplo, &n, &nrhs, const_cast( reinterpret_cast( A ) ), + &lda, const_cast( ipiv ), reinterpret_cast( 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* A, int lda, + const int* ipiv, complex* B, int ldb, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zhetrs_( &uplo, &n, &nrhs, const_cast( reinterpret_cast( A ) ), + &lda, const_cast( ipiv ), reinterpret_cast( 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 +#include + + +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( 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( 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 +#include + + +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( 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( 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 +#include + + +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( 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( 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 +#include + + +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( 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( 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( A ), &lda, + const_cast( 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( A ), &lda, + const_cast( 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( A ), &lda, + const_cast( 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( A ), &lda, + const_cast( 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( A ), &lda, + const_cast( 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( A ), &lda, + const_cast( 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( A ), &lda, + const_cast( 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( A ), &lda, + const_cast( 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 +#include + + +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* A, int lda, complex* B, int ldb, int* info ); + +inline void posv( char uplo, int n, int nrhs, complex* A, int lda, complex* 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* A, int lda, complex* B, int ldb, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cposv_( &uplo, &n, &nrhs, reinterpret_cast( A ), &lda, + reinterpret_cast( 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* A, int lda, complex* B, int ldb, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zposv_( &uplo, &n, &nrhs, reinterpret_cast( A ), &lda, + reinterpret_cast( 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 +#include + + +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* A, int lda, int* info ); + +inline void potrf( char uplo, int n, complex* 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* A, int lda, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cpotrf_( &uplo, &n, reinterpret_cast( 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* A, int lda, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zpotrf_( &uplo, &n, reinterpret_cast( 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 +#include + + +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* A, int lda, int* info ); + +inline void potri( char uplo, int n, complex* 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* A, int lda, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cpotri_( &uplo, &n, reinterpret_cast( 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* A, int lda, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zpotri_( &uplo, &n, reinterpret_cast( 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 +#include + + +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* A, int lda, complex* B, int ldb, int* info ); + +inline void potrs( char uplo, int n, int nrhs, const complex* A, int lda, complex* 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( 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( 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* A, + int lda, complex* B, int ldb, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cpotrs_( &uplo, &n, &nrhs, const_cast( reinterpret_cast( A ) ), + &lda, reinterpret_cast( 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* A, + int lda, complex* B, int ldb, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zpotrs_( &uplo, &n, &nrhs, const_cast( reinterpret_cast( A ) ), + &lda, reinterpret_cast( 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 +#include + + +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* A, int lda, int* ipiv, + complex* B, int ldb, complex* work, int lwork, int* info ); + +inline void sysv( char uplo, int n, int nrhs, complex* A, int lda, int* ipiv, + complex* B, int ldb, complex* 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* A, int lda, int* ipiv, + complex* B, int ldb, complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + csysv_( &uplo, &n, &nrhs, reinterpret_cast( A ), &lda, ipiv, + reinterpret_cast( B ), &ldb, reinterpret_cast( 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* A, int lda, int* ipiv, + complex* B, int ldb, complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zsysv_( &uplo, &n, &nrhs, reinterpret_cast( A ), &lda, ipiv, + reinterpret_cast( B ), &ldb, reinterpret_cast( 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 +#include + + +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* A, int lda, int* ipiv, + complex* work, int lwork, int* info ); + +inline void sytrf( char uplo, int n, complex* A, int lda, int* ipiv, + complex* 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* A, int lda, int* ipiv, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + csytrf_( &uplo, &n, reinterpret_cast( A ), &lda, ipiv, + reinterpret_cast( 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* A, int lda, int* ipiv, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zsytrf_( &uplo, &n, reinterpret_cast( A ), &lda, ipiv, + reinterpret_cast( 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 +#include + + +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* A, int lda, + const int* ipiv, complex* work, int* info ); + +inline void sytri( char uplo, int n, complex* A, int lda, + const int* ipiv, complex* 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( 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( 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* A, int lda, + const int* ipiv, complex* work, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + csytri_( &uplo, &n, reinterpret_cast( A ), &lda, + const_cast( ipiv ), reinterpret_cast( 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* A, int lda, + const int* ipiv, complex* work, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zsytri_( &uplo, &n, reinterpret_cast( A ), &lda, + const_cast( ipiv ), reinterpret_cast( 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 +#include + + +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* A, int lda, const int* ipiv, + complex* B, int ldb, int* info ); + +inline void sytrs( char uplo, int n, int nrhs, const complex* A, int lda, const int* ipiv, + complex* 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( A ), &lda, + const_cast( 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( A ), &lda, + const_cast( 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* A, int lda, + const int* ipiv, complex* B, int ldb, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + csytrs_( &uplo, &n, &nrhs, const_cast( reinterpret_cast( A ) ), + &lda, const_cast( ipiv ), reinterpret_cast( 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* A, int lda, + const int* ipiv, complex* B, int ldb, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zsytrs_( &uplo, &n, &nrhs, const_cast( reinterpret_cast( A ) ), + &lda, const_cast( ipiv ), reinterpret_cast( 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 +#include + + +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* A, + int lda, complex* x, int incX ); + +inline void trsv( char uplo, char trans, char diag, int n, const complex* A, + int lda, complex* 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( 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( 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* A, + int lda, complex* x, int incX ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + ctrsv_( &uplo, &trans, &diag, &n, const_cast( reinterpret_cast( A ) ), + &lda, reinterpret_cast( 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* A, + int lda, complex* x, int incX ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + ztrsv_( &uplo, &trans, &diag, &n, const_cast( reinterpret_cast( A ) ), + &lda, reinterpret_cast( 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 +#include + + +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* A, int lda, int* info ); + +inline void trtri( char uplo, char diag, int n, complex* 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* A, int lda, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + ctrtri_( &uplo, &diag, &n, reinterpret_cast( 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* A, int lda, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + ztrtri_( &uplo, &diag, &n, reinterpret_cast( 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 +#include + + +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* A, + int lda, complex* B, int ldb, int* info ); + +inline void trtrs( char uplo, char trans, char diag, int n, int nrhs, const complex* A, + int lda, complex* 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( 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( 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* A, + int lda, complex* B, int ldb, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + ctrtrs_( &uplo, &trans, &diag, &n, &nrhs, const_cast( reinterpret_cast( A ) ), + &lda, reinterpret_cast( 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* A, + int lda, complex* B, int ldb, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + ztrtrs_( &uplo, &trans, &diag, &n, &nrhs, const_cast( reinterpret_cast( A ) ), + &lda, reinterpret_cast( 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 +#include + + +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* A, int lda, const complex* tau, + complex* work, int lwork, int* info ); + +inline void unglq( int m, int n, int k, complex* A, int lda, const complex* tau, + complex* 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* A, int lda, const complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cunglq_( &m, &n, &k, reinterpret_cast( A ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( 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* A, int lda, const complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zunglq_( &m, &n, &k, reinterpret_cast( A ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( 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 +#include + + +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* A, int lda, const complex* tau, + complex* work, int lwork, int* info ); + +inline void ungql( int m, int n, int k, complex* A, int lda, const complex* tau, + complex* 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* A, int lda, const complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cungql_( &m, &n, &k, reinterpret_cast( A ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( 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* A, int lda, const complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zungql_( &m, &n, &k, reinterpret_cast( A ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( 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 +#include + + +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* A, int lda, const complex* tau, + complex* work, int lwork, int* info ); + +inline void ungqr( int m, int n, int k, complex* A, int lda, const complex* tau, + complex* 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* A, int lda, const complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cungqr_( &m, &n, &k, reinterpret_cast( A ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( 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* A, int lda, const complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zungqr_( &m, &n, &k, reinterpret_cast( A ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( 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 +#include + + +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* A, int lda, const complex* tau, + complex* work, int lwork, int* info ); + +inline void ungrq( int m, int n, int k, complex* A, int lda, const complex* tau, + complex* 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* A, int lda, const complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cungrq_( &m, &n, &k, reinterpret_cast( A ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( 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* A, int lda, const complex* tau, + complex* work, int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zungrq_( &m, &n, &k, reinterpret_cast( A ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( 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 +#include + + +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* A, int lda, + const complex* tau, complex* C, int ldc, complex* work, + int lwork, int* info ); + +inline void unmlq( char side, char trans, int m, int n, int k, const complex* A, int lda, + const complex* tau, complex* C, int ldc, complex* 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* A, int lda, + const complex* tau, complex* C, int ldc, complex* work, + int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cunmlq_( &side, &trans, &m, &n, &k, + const_cast( reinterpret_cast( A ) ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( C ), &ldc, reinterpret_cast( 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* A, int lda, + const complex* tau, complex* C, int ldc, complex* work, + int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zunmlq_( &side, &trans, &m, &n, &k, + const_cast( reinterpret_cast( A ) ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( C ), &ldc, reinterpret_cast( 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 +#include + + +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* A, int lda, + const complex* tau, complex* C, int ldc, complex* work, + int lwork, int* info ); + +inline void unmql( char side, char trans, int m, int n, int k, const complex* A, int lda, + const complex* tau, complex* C, int ldc, complex* 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* A, int lda, + const complex* tau, complex* C, int ldc, complex* work, + int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cunmql_( &side, &trans, &m, &n, &k, + const_cast( reinterpret_cast( A ) ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( C ), &ldc, reinterpret_cast( 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* A, int lda, + const complex* tau, complex* C, int ldc, complex* work, + int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zunmql_( &side, &trans, &m, &n, &k, + const_cast( reinterpret_cast( A ) ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( C ), &ldc, reinterpret_cast( 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 +#include + + +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* A, int lda, + const complex* tau, complex* C, int ldc, complex* work, + int lwork, int* info ); + +inline void unmqr( char side, char trans, int m, int n, int k, const complex* A, int lda, + const complex* tau, complex* C, int ldc, complex* 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* A, int lda, + const complex* tau, complex* C, int ldc, complex* work, + int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cunmqr_( &side, &trans, &m, &n, &k, + const_cast( reinterpret_cast( A ) ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( C ), &ldc, reinterpret_cast( 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* A, int lda, + const complex* tau, complex* C, int ldc, complex* work, + int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zunmqr_( &side, &trans, &m, &n, &k, + const_cast( reinterpret_cast( A ) ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( C ), &ldc, reinterpret_cast( 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 +#include + + +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* A, int lda, + const complex* tau, complex* C, int ldc, complex* work, + int lwork, int* info ); + +inline void unmrq( char side, char trans, int m, int n, int k, const complex* A, int lda, + const complex* tau, complex* C, int ldc, complex* 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* A, int lda, + const complex* tau, complex* C, int ldc, complex* work, + int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + + cunmrq_( &side, &trans, &m, &n, &k, + const_cast( reinterpret_cast( A ) ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( C ), &ldc, reinterpret_cast( 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* A, int lda, + const complex* tau, complex* C, int ldc, complex* work, + int lwork, int* info ) +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + + zunmrq_( &side, &trans, &m, &n, &k, + const_cast( reinterpret_cast( A ) ), &lda, + const_cast( reinterpret_cast( tau ) ), + reinterpret_cast( C ), &ldc, reinterpret_cast( 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// LAPACK LQ DECOMPOSITION FUNCTIONS (GELQF) +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LAPACK LQ decomposition functions (gelqf) */ +//@{ +template< typename MT, bool SO > +inline void gelqf( DenseMatrix& A, ElementType_* 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, or \c complex 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 v(0:i-1) = 0 and +// v(i) = 1. v(i+1:n) is stored on exit in A(i,i+1:n), 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& A, ElementType_* 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_ ); + + typedef ElementType_ ET; + + int m ( numeric_cast( SO ? (~A).rows() : (~A).columns() ) ); + int n ( numeric_cast( SO ? (~A).columns() : (~A).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( m == 0 || n == 0 ) { + return; + } + + int lwork( m*lda ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// LAPACK QL DECOMPOSITION FUNCTIONS (GEQLF) +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LAPACK QL decomposition functions (geqlf) */ +//@{ +template< typename MT, bool SO > +inline void geqlf( DenseMatrix& A, ElementType_* 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, or \c complex 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 v(m-k+i+1:m) = 0 and +// v(m-k+i) = 1. v(1:m-k+i-1) is stored on exit in A(1:m-k+i-1,n-k+i), +// 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& A, ElementType_* 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_ ); + + typedef ElementType_ ET; + + int m ( numeric_cast( SO ? (~A).rows() : (~A).columns() ) ); + int n ( numeric_cast( SO ? (~A).columns() : (~A).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( m == 0 || n == 0 ) { + return; + } + + int lwork( n*lda ); + const std::unique_ptr 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 + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// LAPACK QR DECOMPOSITION FUNCTIONS (GEQRF) +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LAPACK QR decomposition functions (geqrf) */ +//@{ +template< typename MT, bool SO > +inline void geqrf( DenseMatrix& A, ElementType_* 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, or \c complex 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 v(0:i-1) = 0 and +// v(i) = 1. v(i+1:m) is stored on exit in A(i+1:m,i), 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& A, ElementType_* 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_ ); + + typedef ElementType_ ET; + + int m ( numeric_cast( SO ? (~A).rows() : (~A).columns() ) ); + int n ( numeric_cast( SO ? (~A).columns() : (~A).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( m == 0 || n == 0 ) { + return; + } + + int lwork( n*lda ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// LAPACK RQ DECOMPOSITION FUNCTIONS (GERQF) +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LAPACK RQ decomposition functions (gerqf) */ +//@{ +template< typename MT, bool SO > +inline void gerqf( DenseMatrix& A, ElementType_* 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, or \c complex 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 v(n-k+i+1:n) = 0 and +// v(n-k+i) = 1. v(1:n-k+i-1) is stored on exit in A(m-k+i,1:n-k+i-1), +// 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& A, ElementType_* 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_ ); + + typedef ElementType_ ET; + + int m ( numeric_cast( SO ? (~A).rows() : (~A).columns() ) ); + int n ( numeric_cast( SO ? (~A).columns() : (~A).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( m == 0 || n == 0 ) { + return; + } + + int lwork( m*lda ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseVector& b, int* ipiv ); + +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline void gesv( DenseMatrix& A, DenseMatrix& 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, or \c complex 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& A, DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + if( !isSquare( ~A ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" ); + } + + int n ( numeric_cast( (~A).rows() ) ); + int nrhs( 1 ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~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, or \c complex +// 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& A, DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + if( !isSquare( ~A ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" ); + } + + int n ( numeric_cast( (~A).rows() ) ); + int mrhs( numeric_cast( SO2 ? (~B).rows() : (~B).columns() ) ); + int nrhs( numeric_cast( SO2 ? (~B).columns() : (~B).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~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 +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// LAPACK LU DECOMPOSITION FUNCTIONS (GETRF) +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LAPACK LU decomposition functions (getrf) */ +//@{ +template< typename MT, bool SO > +inline void getrf( DenseMatrix& 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, or \c complex 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& 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_ ); + + int m ( numeric_cast( SO ? (~A).rows() : (~A).columns() ) ); + int n ( numeric_cast( SO ? (~A).columns() : (~A).rows() ) ); + int lda ( numeric_cast( (~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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// LAPACK LU-BASED INVERSION FUNCTIONS (GETRI) +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LAPACK LU-based inversion functions (getri) */ +//@{ +template< typename MT, bool SO > +inline void getri( DenseMatrix& 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, or +// \c complex 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& 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_ ); + + typedef ElementType_ ET; + + if( !isSquare( ~A ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid non-square matrix provided" ); + } + + int n ( numeric_cast( (~A).columns() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + int lwork( n*lda ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseVector& b, char trans, const int* ipiv ); + +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline void getrs( const DenseMatrix& A, DenseMatrix& 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, +// or \c complex 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 A( 2UL, 2UL ); // The system matrix A + DynamicVector b( 2UL ); // The right-hand side vector b + DynamicVector ipiv( 2UL ); // Pivoting indices + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicVector 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 A( 2UL, 2UL ); // The system matrix A + DynamicVector b( 2UL ); // The right-hand side vector b + DynamicVector ipiv( 2UL ); // Pivoting indices + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicVector 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& A, DenseVector& 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_ ); + + 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( (~A).rows() ) ); + int nrhs( 1 ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~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, or \c complex 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 A( 2UL, 2UL ); // The system matrix A + DynamicMatrix B( 2UL, 4UL ); // The right-hand side matrix B + DynamicVector ipiv( 2UL ); // Pivoting indices + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicMatrix 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 A( 2UL, 2UL ); // The system matrix A + DynamicMatrix B( 2UL, 4UL ); // The right-hand side matrix B + DynamicVector ipiv( 2UL ); // Pivoting indices + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicMatrix 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& A, DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + 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( (~A).rows() ) ); + int mrhs( numeric_cast( SO2 ? (~B).rows() : (~B).columns() ) ); + int nrhs( numeric_cast( SO2 ? (~B).columns() : (~B).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseVector& b, char uplo, int* ipiv ); + +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline void hesv( DenseMatrix& A, DenseMatrix& 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, or \c complex 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& A, DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + typedef ElementType_ 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( (~A).rows() ) ); + int nrhs( 1 ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~b).size() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::value ) { + ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' ); + } + + int lwork( n*lda ); + const std::unique_ptr 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, or +// \c complex 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& A, DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + typedef ElementType_ 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( (~A).rows() ) ); + int mrhs( numeric_cast( SO2 ? (~B).rows() : (~B).columns() ) ); + int nrhs( numeric_cast( SO2 ? (~B).columns() : (~B).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~B).spacing() ) ); + int info( 0 ); + + if( n != mrhs ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::value ) { + ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' ); + } + + int lwork( n*lda ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// LAPACK LDLH DECOMPOSITION FUNCTIONS (HETRF) +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LAPACK LDLH decomposition functions (hetrf) */ +//@{ +template< typename MT, bool SO > +inline void hetrf( DenseMatrix& 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 or +// \c complex 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& 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_ ); + + typedef ElementType_ 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( (~A).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + int lwork( n*lda ); + const std::unique_ptr work( new ET[lwork] ); + + if( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + + +namespace blaze { + +//================================================================================================= +// +// LAPACK LDLH-BASED INVERSION FUNCTIONS (HETRI) +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LAPACK LDLH-based inversion functions (hetri) */ +//@{ +template< typename MT, bool SO > +inline void hetri( DenseMatrix& 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, or \c complex 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& 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_ ); + + typedef ElementType_ 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( (~A).columns() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::value ) { + ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' ); + } + + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseVector& b, char uplo, const int* ipiv ); + +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline void hetrs( const DenseMatrix& A, DenseMatrix& 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, or \c complex 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 A( 2UL, 2UL ); // The system matrix A + DynamicVector b( 2UL ); // The right-hand side vector b + DynamicVector ipiv( 2UL ); // Pivoting indices + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicVector 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 A( 2UL, 2UL ); // The system matrix A + DynamicVector b( 2UL ); // The right-hand side vector b + DynamicVector ipiv( 2UL ); // Pivoting indices + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicVector 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& A, DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + 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( (~A).rows() ) ); + int nrhs( 1 ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~b).size() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::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, or \c complex 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 A( 2UL, 2UL ); // The system matrix A + DynamicMatrix B( 2UL, 4UL ); // The right-hand side matrix B + DynamicVector ipiv( 2UL ); // Pivoting indices + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicMatrix 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 A( 2UL, 2UL ); // The system matrix A + DynamicMatrix B( 4UL, 2UL ); // The right-hand side matrix B + DynamicVector ipiv( 2UL ); // Pivoting indices + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicMatrix 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& A, DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + 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( (~A).rows() ) ); + int mrhs( numeric_cast( SO2 ? (~B).rows() : (~B).columns() ) ); + int nrhs( numeric_cast( SO2 ? (~B).columns() : (~B).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~B).spacing() ) ); + int info( 0 ); + + if( n != mrhs ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, const ElementType_* 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 A; + DynamicVector 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 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& A, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE( ElementType_ ); + + typedef ElementType_ ET; + + int m ( numeric_cast( SO ? (~A).rows() : (~A).columns() ) ); + int n ( numeric_cast( SO ? (~A).columns() : (~A).rows() ) ); + int k ( min( m, n ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( k == 0 ) { + return; + } + + int lwork( k*lda ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, const ElementType_* 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 A; + DynamicVector 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 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& A, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE( ElementType_ ); + + typedef ElementType_ ET; + + int m ( numeric_cast( SO ? (~A).rows() : (~A).columns() ) ); + int n ( numeric_cast( SO ? (~A).columns() : (~A).rows() ) ); + int k ( min( m, n ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( k == 0 ) { + return; + } + + int lwork( k*lda ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, const ElementType_* 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 A; + DynamicVector 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 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& A, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE( ElementType_ ); + + typedef ElementType_ ET; + + int m ( numeric_cast( SO ? (~A).rows() : (~A).columns() ) ); + int n ( numeric_cast( SO ? (~A).columns() : (~A).rows() ) ); + int k ( min( m, n ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( k == 0 ) { + return; + } + + int lwork( k*lda ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, const ElementType_* 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 A; + DynamicVector 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 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& A, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_BUILTIN_TYPE( ElementType_ ); + + typedef ElementType_ ET; + + int m ( numeric_cast( SO ? (~A).rows() : (~A).columns() ) ); + int n ( numeric_cast( SO ? (~A).columns() : (~A).rows() ) ); + int k ( min( m, n ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( k == 0 ) { + return; + } + + int lwork( k*lda ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& C, const DenseMatrix& A, + char side, char trans, const ElementType_* 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 A; + DynamicMatrix C; + DynamicVector 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& C, const DenseMatrix& A, + char side, char trans, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_ ); + + 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_ ); + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_ ); + + typedef ElementType_ 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( SO1 ? (~C).rows() : (~C).columns() ) ); + int n ( numeric_cast( SO1 ? (~C).columns() : (~C).rows() ) ); + int k ( numeric_cast( min( (~A).rows(), (~A).columns() ) ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldc ( numeric_cast( (~C).spacing() ) ); + int info( 0 ); + + if( m == 0 || n == 0 || k == 0 ) { + return; + } + + if( IsRowMajorMatrix::value ) { + ( side == 'L' )?( side = 'R' ):( side = 'L' ); + } + + if( Xor< IsRowMajorMatrix, IsRowMajorMatrix >::value ) { + ( trans == 'N' )?( trans = 'T' ):( trans = 'N' ); + } + + int lwork( k*ldc ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& C, const DenseMatrix& A, + char side, char trans, const ElementType_* 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 A; + DynamicMatrix C; + DynamicVector 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& C, const DenseMatrix& A, + char side, char trans, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_ ); + + 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_ ); + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_ ); + + typedef ElementType_ 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( SO1 ? (~C).rows() : (~C).columns() ) ); + int n ( numeric_cast( SO1 ? (~C).columns() : (~C).rows() ) ); + int k ( numeric_cast( min( (~A).rows(), (~A).columns() ) ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldc ( numeric_cast( (~C).spacing() ) ); + int info( 0 ); + + if( m == 0 || n == 0 || k == 0 ) { + return; + } + + if( IsRowMajorMatrix::value ) { + ( side == 'L' )?( side = 'R' ):( side = 'L' ); + } + + if( Xor< IsRowMajorMatrix, IsRowMajorMatrix >::value ) { + ( trans == 'N' )?( trans = 'T' ):( trans = 'N' ); + } + + int lwork( k*ldc ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& C, const DenseMatrix& A, + char side, char trans, const ElementType_* 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 A; + DynamicMatrix C; + DynamicVector 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& C, const DenseMatrix& A, + char side, char trans, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_ ); + + 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_ ); + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_ ); + + typedef ElementType_ 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( SO1 ? (~C).rows() : (~C).columns() ) ); + int n ( numeric_cast( SO1 ? (~C).columns() : (~C).rows() ) ); + int k ( numeric_cast( min( (~A).rows(), (~A).columns() ) ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldc ( numeric_cast( (~C).spacing() ) ); + int info( 0 ); + + if( m == 0 || n == 0 || k == 0 ) { + return; + } + + if( IsRowMajorMatrix::value ) { + ( side == 'L' )?( side = 'R' ):( side = 'L' ); + } + + if( Xor< IsRowMajorMatrix, IsRowMajorMatrix >::value ) { + ( trans == 'N' )?( trans = 'T' ):( trans = 'N' ); + } + + int lwork( k*ldc ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& C, const DenseMatrix& A, + char side, char trans, const ElementType_* 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 A; + DynamicMatrix C; + DynamicVector 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& C, const DenseMatrix& A, + char side, char trans, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_ ); + + 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_ ); + BLAZE_CONSTRAINT_MUST_BE_FLOATING_POINT_TYPE( ElementType_ ); + + typedef ElementType_ 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( SO1 ? (~C).rows() : (~C).columns() ) ); + int n ( numeric_cast( SO1 ? (~C).columns() : (~C).rows() ) ); + int k ( numeric_cast( min( (~A).rows(), (~A).columns() ) ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldc ( numeric_cast( (~C).spacing() ) ); + int info( 0 ); + + if( m == 0 || n == 0 || k == 0 ) { + return; + } + + if( IsRowMajorMatrix::value ) { + ( side == 'L' )?( side = 'R' ):( side = 'L' ); + } + + if( Xor< IsRowMajorMatrix, IsRowMajorMatrix >::value ) { + ( trans == 'N' )?( trans = 'T' ):( trans = 'N' ); + } + + int lwork( k*ldc ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseVector& b, char uplo ); + +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline void posv( DenseMatrix& A, DenseMatrix& 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, or \c complex 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& A, DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + 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( (~A).rows() ) ); + int nrhs( 1 ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~b).size() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::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, or +// \c complex 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& A, DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + 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( (~A).rows() ) ); + int mrhs( numeric_cast( SO2 ? (~B).rows() : (~B).columns() ) ); + int nrhs( numeric_cast( SO2 ? (~B).columns() : (~B).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~B).spacing() ) ); + int info( 0 ); + + if( n != mrhs ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// LAPACK LLH (CHOLESKY) DECOMPOSITION FUNCTIONS (POTRF) +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LAPACK LLH (Cholesky) decomposition functions (potrf) */ +//@{ +template< typename MT, bool SO > +inline void potrf( DenseMatrix& 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, or \c complex 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& 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_ ); + + 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( (~A).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// LAPACK LLH-BASED INVERSION FUNCTIONS (POTRI) +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LAPACK LLH-based inversion functions (potri) */ +//@{ +template< typename MT, bool SO > +inline void potri( DenseMatrix& 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, or +// \c complex 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& 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_ ); + + 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( (~A).columns() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseVector& b, char uplo ); + +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline void potrs( const DenseMatrix& A, DenseMatrix& 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, or \c complex 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 A( 2UL, 2UL ); // The system matrix A + DynamicVector b( 2UL ); // The right-hand side vector b + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicVector 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 A( 2UL, 2UL ); // The system matrix A + DynamicVector b( 2UL ); // The right-hand side vector b + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicVector 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& A, DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + 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( (~A).rows() ) ); + int nrhs( 1 ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~b).size() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::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, or \c complex 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 A( 2UL, 2UL ); // The system matrix A + DynamicMatrix B( 2UL, 4UL ); // The right-hand side matrix B + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicMatrix 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 A( 2UL, 2UL ); // The system matrix A + DynamicMatrix B( 4UL, 2UL ); // The right-hand side matrix B + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicMatrix 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& A, DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + 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( (~A).rows() ) ); + int mrhs( numeric_cast( SO2 ? (~B).rows() : (~B).columns() ) ); + int nrhs( numeric_cast( SO2 ? (~B).columns() : (~B).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~B).spacing() ) ); + int info( 0 ); + + if( n != mrhs ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseVector& b, char uplo, int* ipiv ); + +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline void sysv( DenseMatrix& A, DenseMatrix& 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, or \c complex 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& A, DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + typedef ElementType_ 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( (~A).rows() ) ); + int nrhs( 1 ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~b).size() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::value ) { + ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' ); + } + + int lwork( n*lda ); + const std::unique_ptr 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, or +// \c complex 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& A, DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + typedef ElementType_ 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( (~A).rows() ) ); + int mrhs( numeric_cast( SO2 ? (~B).rows() : (~B).columns() ) ); + int nrhs( numeric_cast( SO2 ? (~B).columns() : (~B).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~B).spacing() ) ); + int info( 0 ); + + if( n != mrhs ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::value ) { + ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' ); + } + + int lwork( n*lda ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// LAPACK LDLT DECOMPOSITION FUNCTIONS (SYTRF) +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LAPACK LDLT decomposition functions (sytrf) */ +//@{ +template< typename MT, bool SO > +inline void sytrf( DenseMatrix& 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, or \c complex 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& 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_ ); + + typedef ElementType_ 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( (~A).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + int lwork( n*lda ); + const std::unique_ptr work( new ET[lwork] ); + + if( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// LAPACK LDLT-BASED INVERSION FUNCTIONS (SYTRI) +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LAPACK LDLT-based inversion functions (sytri) */ +//@{ +template< typename MT, bool SO > +inline void sytri( DenseMatrix& 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, or \c complex 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& 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_ ); + + typedef ElementType_ 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( (~A).columns() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::value ) { + ( uplo == 'L' )?( uplo = 'U' ):( uplo = 'L' ); + } + + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseVector& b, char uplo, const int* ipiv ); + +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline void sytrs( const DenseMatrix& A, DenseMatrix& 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, or \c complex 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 A( 2UL, 2UL ); // The system matrix A + DynamicVector b( 2UL ); // The right-hand side vector b + DynamicVector ipiv( 2UL ); // Pivoting indices + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicVector 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 A( 2UL, 2UL ); // The system matrix A + DynamicVector b( 2UL ); // The right-hand side vector b + DynamicVector ipiv( 2UL ); // Pivoting indices + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicVector 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& A, DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + 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( (~A).rows() ) ); + int nrhs( 1 ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~b).size() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::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, or \c complex 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 A( 2UL, 2UL ); // The system matrix A + DynamicMatrix B( 2UL, 4UL ); // The right-hand side matrix B + DynamicVector ipiv( 2UL ); // Pivoting indices + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicMatrix 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 A( 2UL, 2UL ); // The system matrix A + DynamicMatrix B( 4UL, 2UL ); // The right-hand side matrix B + DynamicVector ipiv( 2UL ); // Pivoting indices + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicMatrix 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& A, DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + 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( (~A).rows() ) ); + int mrhs( numeric_cast( SO2 ? (~B).rows() : (~B).columns() ) ); + int nrhs( numeric_cast( SO2 ? (~B).columns() : (~B).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~B).spacing() ) ); + int info( 0 ); + + if( n != mrhs ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseVector& 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, or \c complex 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 A( 2UL, 2UL ); // The system matrix A + DynamicVector b( 2UL ); // The right-hand side vector b + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicVector 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 A( 2UL, 2UL ); // The system matrix A + DynamicVector b( 2UL ); // The right-hand side vector b + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicVector 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& A, DenseVector& 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_ ); + + 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( (~A).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int incX( 1 ); + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// LAPACK TRIANGULAR MATRIX INVERSION FUNCTIONS (TRTRI) +// +//================================================================================================= + +//************************************************************************************************* +/*!\name LAPACK triangular matrix inversion functions (trtri) */ +//@{ +template< typename MT, bool SO > +inline void trtri( DenseMatrix& 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, or \c complex 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& 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_ ); + + 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( (~A).columns() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, DenseVector& b, + char uplo, char trans, char diag ); + +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline void trtrs( const DenseMatrix& A, DenseMatrix& 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, or \c complex 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 A( 2UL, 2UL ); // The system matrix A + DynamicVector b( 2UL ); // The right-hand side vector b + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicVector 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 A( 2UL, 2UL ); // The system matrix A + DynamicVector b( 2UL ); // The right-hand side vector b + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicVector 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& A, DenseVector& 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_ ); + + 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( (~A).rows() ) ); + int nrhs( 1 ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~b).size() ) ); + int info( 0 ); + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::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, or +// \c complex 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 A( 2UL, 2UL ); // The system matrix A + DynamicMatrix B( 2UL, 4UL ); // The right-hand side matrix B + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicMatrix 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 A( 2UL, 2UL ); // The system matrix A + DynamicMatrix B( 2UL, 4UL ); // The right-hand side matrix B + // ... Initialization + + DynamicMatrix D( A ); // Temporary matrix to be decomposed + DynamicMatrix 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& A, DenseMatrix& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_SAME_TYPE( ElementType_, ElementType_ ); + + 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( (~A).rows() ) ); + int mrhs( numeric_cast( SO2 ? (~B).rows() : (~B).columns() ) ); + int nrhs( numeric_cast( SO2 ? (~B).columns() : (~B).rows() ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldb ( numeric_cast( (~B).spacing() ) ); + int info( 0 ); + + if( n != mrhs ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + if( n == 0 ) { + return; + } + + if( IsRowMajorMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, const ElementType_* 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 +// or \c complex 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 cplx; + + DynamicMatrix A; + DynamicVector 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 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& A, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_ ); + + typedef ElementType_ ET; + + int m ( numeric_cast( SO ? (~A).rows() : (~A).columns() ) ); + int n ( numeric_cast( SO ? (~A).columns() : (~A).rows() ) ); + int k ( min( m, n ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( k == 0 ) { + return; + } + + int lwork( k*lda ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, const ElementType_* 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 cplx; + + DynamicMatrix A; + DynamicVector 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 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& A, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_ ); + + typedef ElementType_ ET; + + int n ( numeric_cast( SO ? (~A).columns() : (~A).rows() ) ); + int m ( numeric_cast( SO ? (~A).rows() : (~A).columns() ) ); + int k ( min( m, n ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( k == 0 ) { + return; + } + + int lwork( k*lda ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, const ElementType_* 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 +// or \c complex 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 cplx; + + DynamicMatrix A; + DynamicVector 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 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& A, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_ ); + + typedef ElementType_ ET; + + int m ( numeric_cast( SO ? (~A).rows() : (~A).columns() ) ); + int n ( numeric_cast( SO ? (~A).columns() : (~A).rows() ) ); + int k ( min( m, n ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( k == 0 ) { + return; + } + + int lwork( k*lda ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& A, const ElementType_* 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 cplx; + + DynamicMatrix A; + DynamicVector 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 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& A, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_ ); + + typedef ElementType_ ET; + + int n ( numeric_cast( SO ? (~A).columns() : (~A).rows() ) ); + int m ( numeric_cast( SO ? (~A).rows() : (~A).columns() ) ); + int k ( min( m, n ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int info( 0 ); + + if( k == 0 ) { + return; + } + + int lwork( k*lda ); + const std::unique_ptr 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& C, const DenseMatrix& A, + char side, char trans, const ElementType_* 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 A; + DynamicMatrix C; + DynamicVector 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& C, const DenseMatrix& A, + char side, char trans, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_ ); + + 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_ ); + + typedef ElementType_ 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( SO ? (~C).rows() : (~C).columns() ) ); + int n ( numeric_cast( SO ? (~C).columns() : (~C).rows() ) ); + int k ( numeric_cast( min( (~A).rows(), (~A).columns() ) ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldc ( numeric_cast( (~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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& C, const DenseMatrix& A, + char side, char trans, const ElementType_* 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 A; + DynamicMatrix C; + DynamicVector 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& C, const DenseMatrix& A, + char side, char trans, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_ ); + + 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_ ); + + typedef ElementType_ 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( SO ? (~C).rows() : (~C).columns() ) ); + int n ( numeric_cast( SO ? (~C).columns() : (~C).rows() ) ); + int k ( numeric_cast( min( (~A).rows(), (~A).columns() ) ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldc ( numeric_cast( (~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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& C, DenseMatrix& A, + char side, char trans, ElementType_* 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 A; + DynamicMatrix C; + DynamicVector 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& C, DenseMatrix& A, + char side, char trans, ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_ ); + + 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_ ); + + typedef ElementType_ 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( SO ? (~C).rows() : (~C).columns() ) ); + int n ( numeric_cast( SO ? (~C).columns() : (~C).rows() ) ); + int k ( numeric_cast( min( (~A).rows(), (~A).columns() ) ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldc ( numeric_cast( (~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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& C, const DenseMatrix& A, + char side, char trans, const ElementType_* 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 A; + DynamicMatrix C; + DynamicVector 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& C, const DenseMatrix& A, + char side, char trans, const ElementType_* 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_ ); + + 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COMPLEX_TYPE( ElementType_ ); + + typedef ElementType_ 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( SO ? (~C).rows() : (~C).columns() ) ); + int n ( numeric_cast( SO ? (~C).columns() : (~C).rows() ) ); + int k ( numeric_cast( min( (~A).rows(), (~A).columns() ) ) ); + int lda ( numeric_cast( (~A).spacing() ) ); + int ldc ( numeric_cast( (~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 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 +#include +#include +#include +#include + + +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::ValueType ComplexProxy::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::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::ValueType ComplexProxy::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::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::operator~() +{ + return *static_cast( 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::operator~() const +{ + return *static_cast( 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 + + +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::operator~() +{ + return *static_cast( 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::operator~() const +{ + return *static_cast( 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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::value > +{ + public: + //**Type definitions**************************************************************************** + typedef ResultType_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef CompositeType_ CompositeType; //!< Data type for composite expression templates. + typedef Reference_ Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant matrix value. + typedef ConstPointer_ ConstPointer; //!< Pointer to a constant matrix value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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::Reference + DenseMatrixProxy::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::Reference + DenseMatrixProxy::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::Pointer DenseMatrixProxy::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::Pointer DenseMatrixProxy::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::Iterator + DenseMatrixProxy::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::ConstIterator + DenseMatrixProxy::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::Iterator + DenseMatrixProxy::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::ConstIterator + DenseMatrixProxy::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::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::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::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::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::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::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::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::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::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::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::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::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::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::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::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::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::Iterator + begin( const DenseMatrixProxy& proxy, size_t i ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE typename DenseMatrixProxy::ConstIterator + cbegin( const DenseMatrixProxy& proxy, size_t i ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE typename DenseMatrixProxy::Iterator + end( const DenseMatrixProxy& proxy, size_t i ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE typename DenseMatrixProxy::ConstIterator + cend( const DenseMatrixProxy& proxy, size_t i ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE size_t rows( const DenseMatrixProxy& proxy ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE size_t columns( const DenseMatrixProxy& proxy ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE size_t capacity( const DenseMatrixProxy& proxy ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE size_t capacity( const DenseMatrixProxy& proxy, size_t i ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE size_t nonZeros( const DenseMatrixProxy& proxy ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE size_t nonZeros( const DenseMatrixProxy& proxy, size_t i ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE void resize( const DenseMatrixProxy& proxy, size_t m, size_t n, bool preserve=true ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE void reset( const DenseMatrixProxy& proxy ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE void reset( const DenseMatrixProxy& proxy, size_t i ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE void clear( const DenseMatrixProxy& 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::Iterator + begin( const DenseMatrixProxy& 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::ConstIterator + cbegin( const DenseMatrixProxy& 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::Iterator + end( const DenseMatrixProxy& 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::ConstIterator + cend( const DenseMatrixProxy& 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& 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& 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& 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& 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& 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& 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 > + resize_backend( const DenseMatrixProxy& 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, Not< IsSquare > > > + resize_backend( const DenseMatrixProxy& 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, IsSquare > > + resize_backend( const DenseMatrixProxy& 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& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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::value > +{ + public: + //**Type definitions**************************************************************************** + typedef ResultType_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the vector elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations + typedef CompositeType_ CompositeType; //!< Data type for composite expression templates. + typedef Reference_ Reference; //!< Reference to a non-constant vector value. + typedef ConstReference_ ConstReference; //!< Reference to a constant vector value. + typedef Pointer_ Pointer; //!< Pointer to a non-constant vector value. + typedef ConstPointer_ ConstPointer; //!< Pointer to a constant vector value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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::Reference + DenseVectorProxy::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::Reference + DenseVectorProxy::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::Pointer DenseVectorProxy::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::Iterator DenseVectorProxy::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::ConstIterator DenseVectorProxy::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::Iterator DenseVectorProxy::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::ConstIterator DenseVectorProxy::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::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::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::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::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::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::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::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::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::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::Iterator + begin( const DenseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE typename DenseVectorProxy::ConstIterator + cbegin( const DenseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE typename DenseVectorProxy::Iterator + end( const DenseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE typename DenseVectorProxy::ConstIterator + cend( const DenseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE size_t size( const DenseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE size_t capacity( const DenseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE size_t nonZeros( const DenseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE void resize( const DenseVectorProxy& proxy, size_t n, bool preserve=true ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE void reset( const DenseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE void clear( const DenseVectorProxy& 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::Iterator + begin( const DenseVectorProxy& 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::ConstIterator + cbegin( const DenseVectorProxy& 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::Iterator + end( const DenseVectorProxy& 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::ConstIterator + cend( const DenseVectorProxy& 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& 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& 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& 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 > + resize_backend( const DenseVectorProxy& 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 > + resize_backend( const DenseVectorProxy& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, 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 + , If_< IsDenseVector + , DenseVectorProxy + , SparseVectorProxy > + , If_< IsMatrix + , If_< IsDenseMatrix + , DenseMatrixProxy + , SparseMatrixProxy > + , If_< IsComplex + , ComplexProxy + , DefaultProxy > > > +{}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Proxy operators */ +//@{ +template< typename PT1, typename RT1, typename PT2, typename RT2 > +inline AddExprTrait_ + operator+( const Proxy& lhs, const Proxy& rhs ); + +template< typename PT, typename RT, typename T > +inline DisableIf_< IsProxy, AddExprTrait_ > + operator+( const Proxy& lhs, const T& rhs ); + +template< typename T, typename PT, typename RT > +inline DisableIf_< IsProxy, AddExprTrait_ > + operator+( const T& lhs, const Proxy& rhs ); + +template< typename PT1, typename RT1, typename PT2, typename RT2 > +inline SubExprTrait_ + operator-( const Proxy& lhs, const Proxy& rhs ); + +template< typename PT, typename RT, typename T > +inline DisableIf_< IsProxy, SubExprTrait_ > + operator-( const Proxy& lhs, const T& rhs ); + +template< typename T, typename PT, typename RT > +inline DisableIf_< IsProxy, SubExprTrait_ > + operator-( const T& lhs, const Proxy& rhs ); + +template< typename PT1, typename RT1, typename PT2, typename RT2 > +inline MultExprTrait_ + operator*( const Proxy& lhs, const Proxy& rhs ); + +template< typename PT, typename RT, typename T > +inline DisableIf_< IsProxy, MultExprTrait_ > + operator*( const Proxy& lhs, const T& rhs ); + +template< typename T, typename PT, typename RT > +inline DisableIf_< IsProxy, MultExprTrait_ > + operator*( const T& lhs, const Proxy& rhs ); + +template< typename PT1, typename RT1, typename PT2, typename RT2 > +inline DivExprTrait_ + operator/( const Proxy& lhs, const Proxy& rhs ); + +template< typename PT, typename RT, typename T > +inline DisableIf_< IsProxy, DivExprTrait_ > + operator/( const Proxy& lhs, const T& rhs ); + +template< typename T, typename PT, typename RT > +inline DisableIf_< IsProxy, DivExprTrait_ > + operator/( const T& lhs, const Proxy& rhs ); + +template< typename PT1, typename RT1, typename PT2, typename RT2 > +inline bool operator==( const Proxy& lhs, const Proxy& rhs ); + +template< typename PT, typename RT, typename T > +inline DisableIf_< IsProxy, bool > + operator==( const Proxy& lhs, const T& rhs ); + +template< typename T, typename PT, typename RT > +inline DisableIf_< IsProxy, bool > + operator==( const T& lhs, const Proxy& rhs ); + +template< typename PT1, typename RT1, typename PT2, typename RT2 > +inline bool operator!=( const Proxy& lhs, const Proxy& rhs ); + +template< typename PT, typename RT, typename T > +inline DisableIf_< IsProxy, bool > + operator!=( const Proxy& lhs, const T& rhs ); + +template< typename T, typename PT, typename RT > +inline DisableIf_< IsProxy, bool > + operator!=( const T& lhs, const Proxy& rhs ); + +template< typename PT1, typename RT1, typename PT2, typename RT2 > +inline bool operator<( const Proxy& lhs, const Proxy& rhs ); + +template< typename PT, typename RT, typename T > +inline DisableIf_< IsProxy, bool > + operator<( const Proxy& lhs, const T& rhs ); + +template< typename T, typename PT, typename RT > +inline DisableIf_< IsProxy, bool > + operator<( const T& lhs, const Proxy& rhs ); + +template< typename PT1, typename RT1, typename PT2, typename RT2 > +inline bool operator>( const Proxy& lhs, const Proxy& rhs ); + +template< typename PT, typename RT, typename T > +inline DisableIf_< IsProxy, bool > + operator>( const Proxy& lhs, const T& rhs ); + +template< typename T, typename PT, typename RT > +inline DisableIf_< IsProxy, bool > + operator>( const T& lhs, const Proxy& rhs ); + +template< typename PT1, typename RT1, typename PT2, typename RT2 > +inline bool operator<=( const Proxy& lhs, const Proxy& rhs ); + +template< typename PT, typename RT, typename T > +inline DisableIf_< IsProxy, bool > + operator<=( const Proxy& lhs, const T& rhs ); + +template< typename T, typename PT, typename RT > +inline DisableIf_< IsProxy, bool > + operator<=( const T& lhs, const Proxy& rhs ); + +template< typename PT1, typename RT1, typename PT2, typename RT2 > +inline bool operator>=( const Proxy& lhs, const Proxy& rhs ); + +template< typename PT, typename RT, typename T > +inline DisableIf_< IsProxy, bool > + operator>=( const Proxy& lhs, const T& rhs ); + +template< typename T, typename PT, typename RT > +inline DisableIf_< IsProxy, bool > + operator>=( const T& lhs, const Proxy& rhs ); + +template< typename PT, typename RT > +inline std::ostream& operator<<( std::ostream& os, const Proxy& 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_ + operator+( const Proxy& lhs, const Proxy& 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, AddExprTrait_ > + operator+( const Proxy& 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, AddExprTrait_ > + operator+( const T& lhs, const Proxy& 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_ + operator-( const Proxy& lhs, const Proxy& 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, SubExprTrait_ > + operator-( const Proxy& 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, SubExprTrait_ > + operator-( const T& lhs, const Proxy& 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_ + operator*( const Proxy& lhs, const Proxy& 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, MultExprTrait_ > + operator*( const Proxy& 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, MultExprTrait_ > + operator*( const T& lhs, const Proxy& 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_ + operator/( const Proxy& lhs, const Proxy& 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, DivExprTrait_ > + operator/( const Proxy& 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, DivExprTrait_ > + operator/( const T& lhs, const Proxy& 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& lhs, const Proxy& 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, bool > + operator==( const Proxy& 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, bool > + operator==( const T& lhs, const Proxy& 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& lhs, const Proxy& 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, bool > + operator!=( const Proxy& 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, bool > + operator!=( const T& lhs, const Proxy& 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& lhs, const Proxy& 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, bool > + operator<( const Proxy& 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, bool > + operator<( const T& lhs, const Proxy& 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& lhs, const Proxy& 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, bool > + operator>( const Proxy& 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, bool > + operator>( const T& lhs, const Proxy& 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& lhs, const Proxy& 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, bool > + operator<=( const Proxy& 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, bool > + operator<=( const T& lhs, const Proxy& 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& lhs, const Proxy& 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, bool > + operator>=( const Proxy& 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, bool > + operator>=( const T& lhs, const Proxy& 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& proxy ) +{ + return os << (~proxy).get(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Proxy global functions */ +//@{ +template< typename PT, typename RT > +inline auto trans( const Proxy& proxy ) + -> decltype( trans( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto ctrans( const Proxy& proxy ) + -> decltype( ctrans( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto abs( const Proxy& proxy ) + -> decltype( abs( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto conj( const Proxy& proxy ) + -> decltype( conj( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto real( const Proxy& proxy ) + -> decltype( real( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto imag( const Proxy& proxy ) + -> decltype( imag( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto sqrt( const Proxy& proxy ) + -> decltype( sqrt( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto invsqrt( const Proxy& proxy ) + -> decltype( invsqrt( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto cbrt( const Proxy& proxy ) + -> decltype( cbrt( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto invcbrt( const Proxy& proxy ) + -> decltype( invcbrt( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto floor( const Proxy& proxy ) + -> decltype( floor( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto ceil( const Proxy& proxy ) + -> decltype( ceil( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT, typename ET > +inline auto pow( const Proxy& proxy, const ET& exp ) + -> decltype( pow( std::declval< RepresentedType_ >(), exp ) ); + +template< typename PT, typename RT > +inline auto exp( const Proxy& proxy ) + -> decltype( exp( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto sin( const Proxy& proxy ) + -> decltype( sin( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto asin( const Proxy& proxy ) + -> decltype( asin( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto sinh( const Proxy& proxy ) + -> decltype( sinh( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto asinh( const Proxy& proxy ) + -> decltype( asinh( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto cos( const Proxy& proxy ) + -> decltype( cos( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto acos( const Proxy& proxy ) + -> decltype( acos( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto cosh( const Proxy& proxy ) + -> decltype( cosh( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto acosh( const Proxy& proxy ) + -> decltype( acosh( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto tan( const Proxy& proxy ) + -> decltype( tan( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto atan( const Proxy& proxy ) + -> decltype( atan( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto tanh( const Proxy& proxy ) + -> decltype( tanh( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline auto atanh( const Proxy& proxy ) + -> decltype( atanh( std::declval< RepresentedType_ >() ) ); + +template< typename PT, typename RT > +inline void transpose( const Proxy& proxy ); + +template< typename PT, typename RT > +inline void ctranspose( const Proxy& proxy ); + +template< typename PT, typename RT > +inline void invert( const Proxy& proxy ); + +template< InversionFlag IF, typename PT, typename RT > +inline void invert( const Proxy& proxy ); + +template< typename PT, typename RT > +inline bool isReal( const Proxy& proxy ); + +template< typename PT, typename RT > +inline bool isZero( const Proxy& proxy ); + +template< typename PT, typename RT > +inline bool isOne( const Proxy& proxy ); + +template< typename PT, typename RT > +inline bool isnan( const Proxy& 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& proxy ) + -> decltype( trans( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( ctrans( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( abs( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( conj( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( real( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( imag( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( sqrt( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( invsqrt( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( cbrt( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( invcbrt( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( floor( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( ceil( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy, const ET& exp ) + -> decltype( pow( std::declval< RepresentedType_ >(), 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& proxy ) + -> decltype( exp( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( sin( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( asin( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( sinh( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( asinh( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( cos( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( acos( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( cosh( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( acosh( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( tan( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( atan( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( tanh( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( atanh( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( erf( std::declval< RepresentedType_ >() ) ) +{ + 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& proxy ) + -> decltype( erfc( std::declval< RepresentedType_ >() ) ) +{ + 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& 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& 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& 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( A ); // Inversion of a general matrix + invert( A ); // Inversion of a symmetric indefinite matrix + invert( A ); // Inversion of a Hermitian indefinite matrix + invert( 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& proxy ) +{ + if( (~proxy).isRestricted() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid access to restricted element" ); + } + + invert( (~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& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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::value > +{ + public: + //**Type definitions**************************************************************************** + typedef ResultType_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the sparse matrix elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef CompositeType_ CompositeType; //!< Data type for composite expression templates. + typedef Reference_ Reference; //!< Reference to a non-constant matrix value. + typedef ConstReference_ ConstReference; //!< Reference to a constant matrix value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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::Reference + SparseMatrixProxy::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::Reference + SparseMatrixProxy::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::Iterator + SparseMatrixProxy::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::ConstIterator + SparseMatrixProxy::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::Iterator + SparseMatrixProxy::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::ConstIterator + SparseMatrixProxy::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::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::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::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::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::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::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::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::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::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::Iterator + SparseMatrixProxy::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::Iterator + SparseMatrixProxy::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::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::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::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::Iterator + SparseMatrixProxy::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::Iterator + SparseMatrixProxy::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::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::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::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::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::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::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::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::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::Iterator + SparseMatrixProxy::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::Iterator + SparseMatrixProxy::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::Iterator + SparseMatrixProxy::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::Iterator + begin( const SparseMatrixProxy& proxy, size_t i ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE typename SparseMatrixProxy::ConstIterator + cbegin( const SparseMatrixProxy& proxy, size_t i ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE typename SparseMatrixProxy::Iterator + end( const SparseMatrixProxy& proxy, size_t i ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE typename SparseMatrixProxy::ConstIterator + cend( const SparseMatrixProxy& proxy, size_t i ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE size_t rows( const SparseMatrixProxy& proxy ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE size_t columns( const SparseMatrixProxy& proxy ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE size_t capacity( const SparseMatrixProxy& proxy ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE size_t capacity( const SparseMatrixProxy& proxy, size_t i ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE size_t nonZeros( const SparseMatrixProxy& proxy ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE size_t nonZeros( const SparseMatrixProxy& proxy, size_t i ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE void resize( const SparseMatrixProxy& proxy, size_t m, size_t n, bool preserve=true ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE void reset( const SparseMatrixProxy& proxy ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE void reset( const SparseMatrixProxy& proxy, size_t i ); + +template< typename PT, typename MT > +BLAZE_ALWAYS_INLINE void clear( const SparseMatrixProxy& 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::Iterator + begin( const SparseMatrixProxy& 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::ConstIterator + cbegin( const SparseMatrixProxy& 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::Iterator + end( const SparseMatrixProxy& 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::ConstIterator + cend( const SparseMatrixProxy& 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& 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& 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& 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& 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& 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& 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 > + resize_backend( const SparseMatrixProxy& 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 > + resize_backend( const SparseMatrixProxy& 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& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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::value > +{ + public: + //**Type definitions**************************************************************************** + typedef ResultType_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the sparse vector elements. + typedef ReturnType_ ReturnType; //!< Return type for expression template evaluations. + typedef CompositeType_ CompositeType; //!< Data type for composite expression templates. + typedef Reference_ Reference; //!< Reference to a non-constant vector value. + typedef ConstReference_ ConstReference; //!< Reference to a constant vector value. + typedef Iterator_ Iterator; //!< Iterator over non-constant elements. + typedef ConstIterator_ 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::Reference + SparseVectorProxy::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::Reference + SparseVectorProxy::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::Iterator SparseVectorProxy::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::ConstIterator SparseVectorProxy::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::Iterator SparseVectorProxy::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::ConstIterator SparseVectorProxy::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::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::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::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::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::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::Iterator + SparseVectorProxy::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::Iterator + SparseVectorProxy::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::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::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::Iterator SparseVectorProxy::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::Iterator + SparseVectorProxy::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::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::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::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::Iterator + SparseVectorProxy::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::Iterator + SparseVectorProxy::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::Iterator + SparseVectorProxy::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::Iterator + begin( const SparseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE typename SparseVectorProxy::ConstIterator + cbegin( const SparseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE typename SparseVectorProxy::Iterator + end( const SparseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE typename SparseVectorProxy::ConstIterator + cend( const SparseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE size_t size( const SparseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE size_t capacity( const SparseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE size_t nonZeros( const SparseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE void resize( const SparseVectorProxy& proxy, size_t n, bool preserve=true ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE void reset( const SparseVectorProxy& proxy ); + +template< typename PT, typename VT > +BLAZE_ALWAYS_INLINE void clear( const SparseVectorProxy& 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::Iterator + begin( const SparseVectorProxy& 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::ConstIterator + cbegin( const SparseVectorProxy& 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::Iterator + end( const SparseVectorProxy& 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::ConstIterator + cend( const SparseVectorProxy& 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& 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& 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& 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& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 D; + blaze::CompressedMatrix S; + + // ... Resizing and initialization + + // Creating an archive that writes into a the file "matrices.blaze" + blaze::Archive 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 D1; + blaze::DynamicMatrix D2; + + // Creating an archive that reads from the file "matrices.blaze" + blaze::Archive 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 > > mat; + + // ... Resizing and initialization + + // Creating an archive that writes into a the file "matrix.blaze" + blaze::Archive archive( "matrix.blaze" ); + + // Serialization of the matrix into the archive + archive << mat; + } + + // Deserialization + { + blaze::CompressedMatrix< blaze::DynamicMatrix< blaze::complex > > mat; + + // Creating an archive that reads from the file "matrix.blaze" + blaze::Archive 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::value, IsRowMajorMatrix::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& mat ); + //@} + //********************************************************************************************** + + //**Deserialization functions******************************************************************* + /*!\name Deserialization functions */ + //@{ + template< typename Archive, typename MT, bool SO > + void deserialize( Archive& archive, Matrix& 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& mat ); + + template< typename Archive, typename MT, bool SO > + void serializeMatrix( Archive& archive, const SparseMatrix& 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 > prepareMatrix( DenseMatrix& mat ); + + template< typename MT, bool SO > + DisableIf_< IsResizable > prepareMatrix( SparseMatrix& mat ); + + template< typename MT > + EnableIf_< IsResizable > 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& mat ); + + template< typename Archive, typename MT, bool SO > + void deserializeDenseRowMatrix( Archive& archive, DenseMatrix& mat ); + + template< typename Archive, typename MT, bool SO > + DisableIf_< IsNumeric< ElementType_ > > + deserializeDenseRowMatrix( Archive& archive, SparseMatrix& mat ); + + template< typename Archive, typename MT, bool SO > + EnableIf_< IsNumeric< ElementType_ > > + deserializeDenseRowMatrix( Archive& archive, SparseMatrix& mat ); + + template< typename Archive, typename MT > + EnableIfTrue_< MT::simdEnabled> + deserializeDenseColumnMatrix( Archive& archive, DenseMatrix& mat ); + + template< typename Archive, typename MT, bool SO > + void deserializeDenseColumnMatrix( Archive& archive, DenseMatrix& mat ); + + template< typename Archive, typename MT, bool SO > + DisableIf_< IsNumeric< ElementType_ > > + deserializeDenseColumnMatrix( Archive& archive, SparseMatrix& mat ); + + template< typename Archive, typename MT, bool SO > + EnableIf_< IsNumeric< ElementType_ > > + deserializeDenseColumnMatrix( Archive& archive, SparseMatrix& mat ); + + template< typename Archive, typename MT, bool SO > + void deserializeSparseRowMatrix( Archive& archive, DenseMatrix& mat ); + + template< typename Archive, typename MT > + void deserializeSparseRowMatrix( Archive& archive, SparseMatrix& mat ); + + template< typename Archive, typename MT > + void deserializeSparseRowMatrix( Archive& archive, SparseMatrix& mat ); + + template< typename Archive, typename MT, bool SO > + void deserializeSparseColumnMatrix( Archive& archive, DenseMatrix& mat ); + + template< typename Archive, typename MT > + void deserializeSparseColumnMatrix( Archive& archive, SparseMatrix& mat ); + + template< typename Archive, typename MT > + void deserializeSparseColumnMatrix( Archive& archive, SparseMatrix& 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& 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_ ET; + + archive << uint8_t ( 1U ); + archive << uint8_t ( MatrixValueMapping::value ); + archive << uint8_t ( TypeValueMapping::value ); + archive << uint8_t ( sizeof( ET ) ); + archive << uint64_t( mat.rows() ); + archive << uint64_t( mat.columns() ); + archive << uint64_t( ( IsDenseMatrix::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& mat ) +{ + if( IsRowMajorMatrix::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& mat ) +{ + typedef ConstIterator_ ConstIterator; + + if( IsRowMajorMatrix::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& 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_ 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::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::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 > MatrixSerializer::prepareMatrix( DenseMatrix& 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 > MatrixSerializer::prepareMatrix( SparseMatrix& 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 > 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& mat ) +{ + if( columns_ == 0UL ) return; + + for( size_t i=0UL; i // Storage order +void MatrixSerializer::deserializeDenseRowMatrix( Archive& archive, DenseMatrix& mat ) +{ + typedef ElementType_ ET; + + ET value = ET(); + + for( size_t i=0UL; i> 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_ > > + MatrixSerializer::deserializeDenseRowMatrix( Archive& archive, SparseMatrix& mat ) +{ + DynamicMatrix< ElementType_, 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_ > > + MatrixSerializer::deserializeDenseRowMatrix( Archive& archive, SparseMatrix& mat ) +{ + typedef ElementType_ 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> 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& mat ) +{ + if( rows_ == 0UL ) return; + + for( size_t j=0UL; j // Storage order +void MatrixSerializer::deserializeDenseColumnMatrix( Archive& archive, DenseMatrix& mat ) +{ + typedef ElementType_ ET; + + ET value = ET(); + + for( size_t j=0UL; j> 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_ > > + MatrixSerializer::deserializeDenseColumnMatrix( Archive& archive, SparseMatrix& mat ) +{ + DynamicMatrix< ElementType_, 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_ > > + MatrixSerializer::deserializeDenseColumnMatrix( Archive& archive, SparseMatrix& mat ) +{ + typedef ElementType_ 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> 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& mat ) +{ + typedef ElementType_ ET; + + uint64_t number( 0UL ); + size_t index ( 0UL ); + ET value = ET(); + + for( size_t i=0UL; i> 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& mat ) +{ + typedef ElementType_ ET; + + uint64_t number( 0UL ); + size_t index ( 0UL ); + ET value = ET(); + + for( size_t i=0UL; i> 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& mat ) +{ + CompressedMatrix< ElementType_, 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& mat ) +{ + typedef ElementType_ ET; + + uint64_t number( 0UL ); + size_t index ( 0UL ); + ET value = ET(); + + for( size_t j=0UL; j> 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& mat ) +{ + CompressedMatrix< ElementType_, 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& mat ) +{ + typedef ElementType_ ET; + + uint64_t number( 0UL ); + size_t index ( 0UL ); + ET value = ET(); + + for( size_t j=0UL; j> 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 +{ + enum { value = 1 }; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the MatrixValueMappingHelper class template for column-major dense matrices. +*/ +template<> +struct MatrixSerializer::MatrixValueMappingHelper +{ + enum { value = 5 }; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the MatrixValueMappingHelper class template for row-major sparse matrices. +*/ +template<> +struct MatrixSerializer::MatrixValueMappingHelper +{ + enum { value = 3 }; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the MatrixValueMappingHelper class template for column-major sparse matrices. +*/ +template<> +struct MatrixSerializer::MatrixValueMappingHelper +{ + 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 D; + blaze::CompressedMatrix S; + + // ... Resizing and initialization + + // Creating an archive that writes into a the file "matrices.blaze" + blaze::Archive 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 D1; + blaze::DynamicMatrix D2; + + // ... Resizing and initialization + + // Creating an archive that reads from the file "matrices.blaze" + blaze::Archive 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& 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& 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 d; + blaze::CompressedVector s; + + // ... Resizing and initialization + + // Creating an archive that writes into a the file "vectors.blaze" + blaze::Archive 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 d1; + blaze::DynamicVector d2; + + // Creating an archive that reads from the file "vectors.blaze" + blaze::Archive 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 > > vec; + + // ... Resizing and initialization + + // Creating an archive that writes into a the file "vector.blaze" + blaze::Archive archive( "vector.blaze" ); + + // Serialization of the vector into the archive + archive << vec; + } + + // Deserialization + { + blaze::CompressedVector< blaze::DynamicVector< blaze::complex > > vec; + + // Creating an archive that reads from the file "vector.blaze" + blaze::Archive 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 +#include +#include +#include +#include + + +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 +{ + public: + //********************************************************************************************** + enum { value = 0 }; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the TypeValueMappingHelper for signed integral data types. +// \ingroup math_serialization +*/ +template<> +struct TypeValueMappingHelper +{ + public: + //********************************************************************************************** + enum { value = 1 }; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the TypeValueMappingHelper for unsigned integral data types. +// \ingroup math_serialization +*/ +template<> +struct TypeValueMappingHelper +{ + public: + //********************************************************************************************** + enum { value = 2 }; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the TypeValueMappingHelper for floating-point data types. +// \ingroup math_serialization +*/ +template<> +struct TypeValueMappingHelper +{ + public: + //********************************************************************************************** + enum { value = 3 }; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the TypeValueMappingHelper for complex data types. +// \ingroup math_serialization +*/ +template<> +struct TypeValueMappingHelper +{ + 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::value && IsSigned::value + , IsIntegral::value && IsUnsigned::value + , IsFloatingPoint::value + , IsComplex::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 d; + blaze::CompressedVector s; + + // ... Resizing and initialization + + // Creating an archive that writes into a the file "vectors.blaze" + blaze::Archive 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 d1; + blaze::DynamicVector d2; + + // Creating an archive that reads from the file "vectors.blaze" + blaze::Archive 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 > > vec; + + // ... Resizing and initialization + + // Creating an archive that writes into a the file "vector.blaze" + blaze::Archive archive( "vector.blaze" ); + + // Serialization of the vector into the archive + archive << vec; + } + + // Deserialization + { + blaze::CompressedVector< blaze::DynamicVector< blaze::complex > > vec; + + // Creating an archive that reads from the file "vector.blaze" + blaze::Archive 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::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& vec ); + //@} + //********************************************************************************************** + + //**Deserialization functions********************************************************************* + /*!\name Deserialization functions */ + //@{ + template< typename Archive, typename VT, bool TF > + void deserialize( Archive& archive, Vector& 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& vec ); + + template< typename Archive, typename VT, bool TF > + void serializeVector( Archive& archive, const SparseVector& 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 > prepareVector( DenseVector& vec ); + + template< typename VT, bool TF > + DisableIf_< IsResizable > prepareVector( SparseVector& vec ); + + template< typename VT > + EnableIf_< IsResizable > 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& vec ); + + template< typename Archive, typename VT, bool TF > + EnableIfTrue_< VT::simdEnabled > + deserializeDenseVector( Archive& archive, DenseVector& vec ); + + template< typename Archive, typename VT, bool TF > + void deserializeDenseVector( Archive& archive, SparseVector& vec ); + + template< typename Archive, typename VT, bool TF > + void deserializeSparseVector( Archive& archive, DenseVector& vec ); + + template< typename Archive, typename VT, bool TF > + void deserializeSparseVector( Archive& archive, SparseVector& 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& 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_ ET; + + archive << uint8_t ( 1U ); + archive << uint8_t ( VectorValueMapping::value ); + archive << uint8_t ( TypeValueMapping::value ); + archive << uint8_t ( sizeof( ET ) ); + archive << uint64_t( vec.size() ); + archive << uint64_t( IsDenseVector::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& 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& vec ) +{ + typedef ConstIterator_ 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& 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_ 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::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::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 > VectorSerializer::prepareVector( DenseVector& 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 > VectorSerializer::prepareVector( SparseVector& 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 > 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& vec ) +{ + typedef ElementType_ 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& 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& vec ) +{ + typedef ElementType_ 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& vec ) +{ + typedef ElementType_ 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& vec ) +{ + typedef ElementType_ 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 +{ + enum { value = 0 }; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the VectorValueMappingHelper class template for sparse vectors. +*/ +template<> +struct VectorSerializer::VectorValueMappingHelper +{ + 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 d; + blaze::CompressedVector s; + + // ... Resizing and initialization + + // Creating an archive that writes into a the file "vectors.blaze" + blaze::Archive 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 d1; + blaze::DynamicVector d2; + + // ... Resizing and initialization + + // Creating an archive that reads from the file "vectors.blaze" + blaze::Archive 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& 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& 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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 + + +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 +#include +#include +#include +#include +#include + + +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 a( 1.0, 2.0 ); + const blaze::complex 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 > 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 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::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 > 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 > 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::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 + + +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 + + +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 +#include +#include +#include + + +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( 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( 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( 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( 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( 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( 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( 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( 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( 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 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 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 a, complex 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 + + +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 + + +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 + + +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 + + +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 +#include +#include +#include + + +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 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 > 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 +#include +#include +#include +#include + + +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 > > +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 +#include +#include +#include +#include +#include + + +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 > > +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 > > +inline auto invsqrt( const complex& 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 +#include +#include +#include + + +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 inv( const complex& 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( 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 inv( const complex& 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( 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 inv( const complex& 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( 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& 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& 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& 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 +#include +#include +#include +#include + + +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::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& v ) noexcept( IsBuiltin::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 +#include +#include +#include +#include +#include + + +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 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 c2( 0.0, 0.0 ); // isDivisor( c2 ) returns false + \endcode +*/ +template< typename Type, typename = EnableIf_< IsNumeric > > +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 +#include +#include + + +//************************************************************************************************* +// 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, 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 +#include +#include +#include +#include +#include + + +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 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 c2( 0.0, 1.0 ); // isOne( c2 ) returns false + \endcode +*/ +template< typename Type > +BLAZE_ALWAYS_INLINE EnableIf_< IsNumeric, 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, 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 +#include +#include +#include +#include + + +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 c1( 1.0, 0.0 ); // isReal( c1 ) returns true + complex c2( 0.0, 1.0 ); // isReal( c2 ) returns false + + blaze::DynamicVector vec; // isReal( vec ) returns false + blaze::DynamicMatrix mat; // isReal( mat ) returns false + \endcode +*/ +template< typename Type > +BLAZE_ALWAYS_INLINE bool isReal( const Type& v ) noexcept +{ + UNUSED_PARAMETER( v ); + + return IsBuiltin::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& v ) noexcept( IsBuiltin::value ) +{ + return IsBuiltin::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 +#include +#include +#include +#include +#include + + +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 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 c2( 1.0, 0.0 ); // isZero( c2 ) returns false + \endcode +*/ +template< typename Type > +BLAZE_ALWAYS_INLINE EnableIf_< IsNumeric, 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, 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 + + +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 + + +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 + + +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 +#include +#include + + +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 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 > 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 + + +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 +#include +#include +#include +#include + + +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, IsComplex >, 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 + + +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 + + +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 + + +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 +#include + + +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_ 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 + + +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 + + +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 +#include +#include + + +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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& a, const SIMDi8& 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& a, const SIMDi8& 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& a, const SIMDci8& 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& a, const SIMDi16& 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& a, const SIMDi16& 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& a, const SIMDci16& 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& a, const SIMDi32& 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& a, const SIMDi32& 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& a, const SIMDci32& 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& a, const SIMDi64& 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& a, const SIMDi64& 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& a, const SIMDci64& 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& a, const SIMDf32& 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& a, const SIMDf64& 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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& 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& 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 +#include +#include +#include +#include +#include + + +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; + 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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDint8& operator=( const SIMDi8& 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; + 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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDuint8& operator=( const SIMDi8& 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; + using ValueType = complex; + +#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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDcint8& operator=( const SIMDci8& 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; + using ValueType = complex; + +#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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDcuint8& operator=( const SIMDci8& 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; + 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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDint16& operator=( const SIMDi16& 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; + 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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDuint16& operator=( const SIMDi16& 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; + using ValueType = complex; + +#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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDcint16& operator=( const SIMDci16& 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; + using ValueType = complex; + +#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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDcuint16& operator=( const SIMDci16& 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; + 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( &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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDint32& operator=( const SIMDi32& 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; + 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( &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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDuint32& operator=( const SIMDi32& 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; + using ValueType = complex; + +#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( &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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDcint32& operator=( const SIMDci32& 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; + using ValueType = complex; + +#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( &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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDcuint32& operator=( const SIMDci32& 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; + 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( &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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDint64& operator=( const SIMDi64& 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; + 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( &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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDuint64& operator=( const SIMDi64& 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; + using ValueType = complex; + +#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( &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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDcint64& operator=( const SIMDci64& 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; + using ValueType = complex; + +#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( &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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDcuint64& operator=( const SIMDci64& 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; + 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( &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( &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( &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& v ) noexcept : value( (~v).eval().value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDfloat& operator=( const SIMDf32& 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; + using ValueType = complex; + +#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( &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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDcfloat& operator=( const SIMDcf32& 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; + 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( &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( &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( &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& v ) noexcept : value( (~v).eval().value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDdouble& operator=( const SIMDf64& 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; + using ValueType = complex; + +#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( &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( &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( &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& v ) noexcept : value( (~v).value ) {} + + template< typename T > + BLAZE_ALWAYS_INLINE SIMDcdouble& operator=( const SIMDcf64& 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& lhs, const SIMDPack& 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& lhs, const SIMDPack& 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& lhs, const SIMDPack& 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& lhs, const SIMDPack& 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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& 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& 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& 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& 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& 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& 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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& 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& 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 +#include + + +namespace blaze { + +//================================================================================================= +// +// DERIVED SIMD TYPES +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief The SIMD data type for 'char'. +// \ingroup simd +*/ +typedef SIMDTrait::Type SIMDchar; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'signed char'. +// \ingroup simd +*/ +typedef SIMDTrait::Type SIMDschar; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'unsigned char'. +// \ingroup simd +*/ +typedef SIMDTrait::Type SIMDuchar; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'wchar_t'. +// \ingroup simd +*/ +typedef SIMDTrait::Type SIMDwchar; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'complex'. +// \ingroup simd +*/ +typedef SIMDTrait< complex >::Type SIMDcchar; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'complex'. +// \ingroup simd +*/ +typedef SIMDTrait< complex >::Type SIMDcschar; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'complex'. +// \ingroup simd +*/ +typedef SIMDTrait< complex >::Type SIMDcuchar; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'complex'. +// \ingroup simd +*/ +typedef SIMDTrait< complex >::Type SIMDcwchar; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'short'. +// \ingroup simd +*/ +typedef SIMDTrait::Type SIMDshort; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'unsigned short'. +// \ingroup simd +*/ +typedef SIMDTrait::Type SIMDushort; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'complex'. +// \ingroup simd +*/ +typedef SIMDTrait< complex >::Type SIMDcshort; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'complex'. +// \ingroup simd +*/ +typedef SIMDTrait< complex >::Type SIMDcushort; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'int'. +// \ingroup simd +*/ +typedef SIMDTrait::Type SIMDint; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'unsigned int'. +// \ingroup simd +*/ +typedef SIMDTrait::Type SIMDuint; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'complex'. +// \ingroup simd +*/ +typedef SIMDTrait< complex >::Type SIMDcint; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'complex'. +// \ingroup simd +*/ +typedef SIMDTrait< complex >::Type SIMDcuint; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'long int'. +// \ingroup simd +*/ +typedef SIMDTrait::Type SIMDlong; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'unsigned long int'. +// \ingroup simd +*/ +typedef SIMDTrait::Type SIMDulong; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'complex'. +// \ingroup simd +*/ +typedef SIMDTrait< complex >::Type SIMDclong; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief The SIMD data type for 'complex'. +// \ingroup simd +*/ +typedef SIMDTrait< complex >::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 +#include +#include + + +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& a, const SIMDf32& 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& a, const SIMDf64& 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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& 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& 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 +#include +#include +#include +#include +#include + + +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 > +{ + //**Type definitions**************************************************************************** + using This = SIMDf32FmaddExpr; //!< Type of this SIMDf32FMaddExpr instance. + using BaseType = SIMDf32; //!< 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 > +{ + //**Type definitions**************************************************************************** + using This = SIMDf32MultExpr; //!< Type of this SIMDf32FMsubExpr instance. + using BaseType = SIMDf32; //!< 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 + operator+( const SIMDf32MultExpr& a, const SIMDf32& b ) +{ + return SIMDf32FmaddExpr( 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 + operator+( const SIMDf32& a, const SIMDf32MultExpr& b ) +{ + return SIMDf32FmaddExpr( 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 > + operator+( const SIMDf32MultExpr& a, const SIMDf32MultExpr& b ) +{ + return SIMDf32FmaddExpr< T1, T2, SIMDf32MultExpr >( 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& a, const SIMDf32& 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& a, const SIMDf32FmaddExpr& 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 > + operator+( const SIMDf32FmaddExpr& a, const SIMDf32MultExpr& b ) +{ + return SIMDf32FmaddExpr< T4, T5, SIMDf32FmaddExpr >( 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 > + operator+( const SIMDf32MultExpr& a, const SIMDf32FmaddExpr& b ) +{ + return SIMDf32FmaddExpr< T1, T2, SIMDf32FmaddExpr >( 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& a, const SIMDf32FmaddExpr& 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& a, const SIMDf32FmsubExpr& 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& a, const SIMDf32FmaddExpr& 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& a, const SIMDf32FmsubExpr& 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 + operator-( const SIMDf32MultExpr& a, const SIMDf32& b ) +{ + return SIMDf32FmsubExpr( 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 > + operator-( const SIMDf32MultExpr& a, const SIMDf32MultExpr& b ) +{ + return SIMDf32FmsubExpr< T1, T2, SIMDf32MultExpr >( 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& a, const SIMDf32& 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& a, const SIMDf32MultExpr& 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 > + operator-( const SIMDf32MultExpr& a, const SIMDf32FmsubExpr& b ) +{ + return SIMDf32FmsubExpr< T1, T2, SIMDf32FmsubExpr >( 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& a, const SIMDf32FmaddExpr& 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& a, const SIMDf32FmsubExpr& 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& a, const SIMDf32FmaddExpr& 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& a, const SIMDf32FmsubExpr& 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 > +{ + //**Type definitions**************************************************************************** + using This = SIMDf64FmaddExpr; //!< Type of this SIMDf64FMaddExpr instance. + using BaseType = SIMDf64; //!< 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 > +{ + //**Type definitions**************************************************************************** + using This = SIMDf64MultExpr; //!< Type of this SIMDf64FMsubExpr instance. + using BaseType = SIMDf64; //!< 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 + operator+( const SIMDf64MultExpr& a, const SIMDf64& b ) +{ + return SIMDf64FmaddExpr( 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 + operator+( const SIMDf64& a, const SIMDf64MultExpr& b ) +{ + return SIMDf64FmaddExpr( 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 > + operator+( const SIMDf64MultExpr& a, const SIMDf64MultExpr& b ) +{ + return SIMDf64FmaddExpr< T1, T2, SIMDf64MultExpr >( 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& a, const SIMDf64& 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& a, const SIMDf64FmaddExpr& 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 > + operator+( const SIMDf64FmaddExpr& a, const SIMDf64MultExpr& b ) +{ + return SIMDf64FmaddExpr< T4, T5, SIMDf64FmaddExpr >( 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 > + operator+( const SIMDf64MultExpr& a, const SIMDf64FmaddExpr& b ) +{ + return SIMDf64FmaddExpr< T1, T2, SIMDf64FmaddExpr >( 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& a, const SIMDf64FmaddExpr& 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& a, const SIMDf64FmsubExpr& 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& a, const SIMDf64FmaddExpr& 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& a, const SIMDf64FmsubExpr& 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 + operator-( const SIMDf64MultExpr& a, const SIMDf64& b ) +{ + return SIMDf64FmsubExpr( 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 > + operator-( const SIMDf64MultExpr& a, const SIMDf64MultExpr& b ) +{ + return SIMDf64FmsubExpr< T1, T2, SIMDf64MultExpr >( 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& a, const SIMDf64& 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& a, const SIMDf64MultExpr& 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 > + operator-( const SIMDf64MultExpr& a, const SIMDf64FmsubExpr& b ) +{ + return SIMDf64FmsubExpr< T1, T2, SIMDf64FmsubExpr >( 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& a, const SIMDf64FmaddExpr& 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& a, const SIMDf64FmsubExpr& 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& a, const SIMDf64FmaddExpr& 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& a, const SIMDf64FmsubExpr& 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 +#include +#include + + +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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, HasSize > + , If_< IsSigned, 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( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_load_si128( reinterpret_cast( 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, HasSize > + , If_< IsSigned, SIMDcint8, SIMDcuint8 > > + loada( const complex* address ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( T ) ); + BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" ); + +#if BLAZE_AVX2_MODE + return _mm256_load_si256( reinterpret_cast( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_load_si128( reinterpret_cast( 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, HasSize > + , If_< IsSigned, 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( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_load_si128( reinterpret_cast( 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, HasSize > + , If_< IsSigned, SIMDcint16, SIMDcuint16 > > + loada( const complex* address ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( T ) ); + BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" ); + +#if BLAZE_AVX2_MODE + return _mm256_load_si256( reinterpret_cast( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_load_si128( reinterpret_cast( 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, HasSize > + , If_< IsSigned, 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( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_load_si128( reinterpret_cast( 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, HasSize > + , If_< IsSigned, SIMDcint32, SIMDcuint32 > > + loada( const complex* address ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_load_si128( reinterpret_cast( 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, HasSize > + , If_< IsSigned, 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( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_load_si128( reinterpret_cast( 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, HasSize > + , If_< IsSigned, SIMDcint64, SIMDcuint64 > > + loada( const complex* address ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_load_si128( reinterpret_cast( address ) ); +#else + return If_< IsSigned, 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' values. +// \ingroup simd +// +// \param address The first 'complex' value to be loaded. +// \return The loaded vector of 'complex' values. +// +// This function loads a vector of '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). +*/ +BLAZE_ALWAYS_INLINE const SIMDcfloat loada( const complex* address ) noexcept +{ + BLAZE_STATIC_ASSERT ( sizeof( complex ) == 2UL*sizeof( float ) ); + BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" ); + +#if BLAZE_MIC_MODE + return _mm512_load_ps( reinterpret_cast( address ) ); +#elif BLAZE_AVX_MODE + return _mm256_load_ps( reinterpret_cast( address ) ); +#elif BLAZE_SSE_MODE + return _mm_load_ps( reinterpret_cast( 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' values. +// \ingroup simd +// +// \param address The first 'complex' value to be loaded. +// \return The loaded vector of 'complex' values. +// +// This function loads a vector of '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). +*/ +BLAZE_ALWAYS_INLINE const SIMDcdouble loada( const complex* address ) noexcept +{ + BLAZE_STATIC_ASSERT ( sizeof( complex ) == 2UL*sizeof( double ) ); + BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" ); + +#if BLAZE_MIC_MODE + return _mm512_load_pd( reinterpret_cast( address ) ); +#elif BLAZE_AVX_MODE + return _mm256_load_pd( reinterpret_cast( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_load_pd( reinterpret_cast( 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, HasSize > + , If_< IsSigned, SIMDint8, SIMDuint8 > > + loadu( const T* address ) noexcept +{ +#if BLAZE_AVX2_MODE + return _mm256_loadu_si256( reinterpret_cast( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_loadu_si128( reinterpret_cast( 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, HasSize > + , If_< IsSigned, SIMDcint8, SIMDcuint8 > > + loadu( const complex* address ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( T ) ); + +#if BLAZE_AVX2_MODE + return _mm256_loadu_si256( reinterpret_cast( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_loadu_si128( reinterpret_cast( 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, HasSize > + , If_< IsSigned, SIMDint16, SIMDuint16 > > + loadu( const T* address ) noexcept +{ +#if BLAZE_AVX2_MODE + return _mm256_loadu_si256( reinterpret_cast( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_loadu_si128( reinterpret_cast( 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, HasSize > + , If_< IsSigned, SIMDcint16, SIMDcuint16 > > + loadu( const complex* address ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( T ) ); + +#if BLAZE_AVX2_MODE + return _mm256_loadu_si256( reinterpret_cast( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_loadu_si128( reinterpret_cast( 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, HasSize > + , If_< IsSigned, 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( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_loadu_si128( reinterpret_cast( 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, HasSize > + , If_< IsSigned, SIMDcint32, SIMDcuint32 > > + loadu( const complex* address ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_loadu_si128( reinterpret_cast( 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, HasSize > + , If_< IsSigned, 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( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_loadu_si128( reinterpret_cast( 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, HasSize > + , If_< IsSigned, SIMDcint64, SIMDcuint64 > > + loadu( const complex* address ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_loadu_si128( reinterpret_cast( address ) ); +#else + return If_< IsSigned, 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' values. +// \ingroup simd +// +// \param address The first 'complex' value to be loaded. +// \return The loaded vector of 'complex' values. +// +// This function loads a vector of 'complex' 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* address ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + +#if BLAZE_MIC_MODE + __m512 v1 = _mm512_setzero_ps(); + v1 = _mm512_loadunpacklo_ps( v1, reinterpret_cast( address ) ); + v1 = _mm512_loadunpackhi_ps( v1, reinterpret_cast( address+8UL ) ); + return v1; +#elif BLAZE_AVX_MODE + return _mm256_loadu_ps( reinterpret_cast( address ) ); +#elif BLAZE_SSE_MODE + return _mm_loadu_ps( reinterpret_cast( 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' values. +// \ingroup simd +// +// \param address The first 'complex' value to be loaded. +// \return The loaded vector of 'complex' values. +// +// This function loads a vector of 'complex' 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* address ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + +#if BLAZE_MIC_MODE + __m512d v1 = _mm512_setzero_pd(); + v1 = _mm512_loadunpacklo_pd( v1, reinterpret_cast( address ) ); + v1 = _mm512_loadunpackhi_pd( v1, reinterpret_cast( address+4UL ) ); + return v1; +#elif BLAZE_AVX_MODE + return _mm256_loadu_pd( reinterpret_cast( address ) ); +#elif BLAZE_SSE2_MODE + return _mm_loadu_pd( reinterpret_cast( 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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& a, const SIMDi16& 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& a, const SIMDi16& 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& a, const SIMDci16& 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& a, const SIMDi32& 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& a, const SIMDi32& 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& a, const SIMDci32& 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 > +{ + //**Type definitions**************************************************************************** + using This = SIMDf32MultExpr; //!< Type of this SIMDf32MultExpr instance. + using BaseType = SIMDf32; //!< 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 + operator*( const SIMDf32& a, const SIMDf32& b ) noexcept +{ + return SIMDf32MultExpr( ~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 > +{ + //**Type definitions**************************************************************************** + using This = SIMDf64MultExpr; //!< Type of this SIMDf64MultExpr instance. + using BaseType = SIMDf64; //!< 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 + operator*( const SIMDf64& a, const SIMDf64& b ) noexcept +{ + return SIMDf64MultExpr( ~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 +#include +#include + + +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& a, const SIMDf32& 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& a, const SIMDf64& 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 +#include +#include + + +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 sum( const SIMDcint8& a ) noexcept +{ +#if BLAZE_AVX2_MODE + return complex( 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( 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 sum( const SIMDcint16& a ) noexcept +{ +#if BLAZE_AVX2_MODE + return complex( a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] ); +#elif BLAZE_SSE2_MODE + return complex( 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 sum( const SIMDcint32& a ) noexcept +{ +#if BLAZE_MIC_MODE + return complex( a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] ); +#elif BLAZE_AVX2_MODE + return complex( a[0] + a[1] + a[2] + a[3] ); +#elif BLAZE_SSE2_MODE + return complex( 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 sum( const SIMDcint64& a ) noexcept +{ +#if BLAZE_MIC_MODE + return complex( a[0] + a[1] + a[2] + a[3] ); +#elif BLAZE_AVX2_MODE + return complex( 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 sum( const SIMDcfloat& a ) noexcept +{ +#if BLAZE_MIC_MODE + return complex( a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] ); +#elif BLAZE_AVX_MODE + return complex( a[0] + a[1] + a[2] + a[3] ); +#elif BLAZE_SSE_MODE + return complex( 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 sum( const SIMDcdouble& a ) noexcept +{ +#if BLAZE_MIC_MODE + return complex( a[0] + a[1] + a[2] + a[3] ); +#elif BLAZE_AVX_MODE + return complex( 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 + + +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( 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( 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsIntegral, Has1Byte > > > +{ + using Type = If_< IsSigned, 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, EnableIf_< And< IsNumeric, IsIntegral, Has1Byte > > > +{ + using Type = If_< IsSigned, SIMDcint8, SIMDcuint8 >; + enum : size_t { size = Type::size }; + + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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, IsIntegral, Has2Bytes > > > +{ + using Type = If_< IsSigned, 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, EnableIf_< And< IsNumeric, IsIntegral, Has2Bytes > > > +{ + using Type = If_< IsSigned, SIMDcint16, SIMDcuint16 >; + enum : size_t { size = Type::size }; + + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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, IsIntegral, Has4Bytes > > > +{ + using Type = If_< IsSigned, 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, EnableIf_< And< IsNumeric, IsIntegral, Has4Bytes > > > +{ + using Type = If_< IsSigned, SIMDcint32, SIMDcuint32 >; + enum : size_t { size = Type::size }; + + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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, IsIntegral, Has8Bytes > > > +{ + using Type = If_< IsSigned, 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, EnableIf_< And< IsNumeric, IsIntegral, Has8Bytes > > > +{ + using Type = If_< IsSigned, SIMDcint64, SIMDcuint64 >; + enum : size_t { size = Type::size }; + + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( T ) ); +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the SIMDTraitBase class template for 'float'. +// \ingroup simd +*/ +template<> +struct SIMDTraitBase +{ + using Type = SIMDfloat; + enum : size_t { size = Type::size }; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the SIMDTraitBase class template for 'complex'. +// \ingroup simd +*/ +template<> +struct SIMDTraitBase< complex > +{ + using Type = SIMDcfloat; + enum : size_t { size = Type::size }; + + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the SIMDTraitBase class template for 'double'. +// \ingroup simd +*/ +template<> +struct SIMDTraitBase +{ + using Type = SIMDdouble; + enum : size_t { size = Type::size }; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the SIMDTraitBase class template for 'complex'. +// \ingroup simd +*/ +template<> +struct SIMDTraitBase< complex > +{ + using Type = SIMDcdouble; + enum : size_t { size = Type::size }; + + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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_ > +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\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::Type; + using Type2 = SIMDTrait_; + \endcode +*/ +template< typename T > +using SIMDTrait_ = typename SIMDTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, HasSize > + , If_< IsSigned, 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, HasSize > + , If_< IsSigned, SIMDcint8, SIMDcuint8 > > + set( complex 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 ) == 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, HasSize > + , If_< IsSigned, 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, HasSize > + , If_< IsSigned, SIMDcint16, SIMDcuint16 > > + set( complex 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 ) == 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, HasSize > + , If_< IsSigned, 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, HasSize > + , If_< IsSigned, SIMDcint32, SIMDcuint32 > > + set( complex 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 ) == 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, HasSize > + , If_< IsSigned, 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, HasSize > + , If_< IsSigned, SIMDcint64, SIMDcuint64 > > + set( complex 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 ) == 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' value. +// \ingroup simd +// +// \param value The given 'complex' value. +// \return The set vector of 'complex' values. +*/ +BLAZE_ALWAYS_INLINE const SIMDcfloat set( const complex& 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 ) == 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' value. +// \ingroup simd +// +// \param value The given 'complex' value. +// \return The set vector of 'complex' values. +*/ +BLAZE_ALWAYS_INLINE const SIMDcdouble set( const complex& 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 ) == 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 +#include +#include + + +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& 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& 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& 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& 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& 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& 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& 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& 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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, HasSize > > + storea( T1* address, const SIMDi8& 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, HasSize > > + storea( complex* address, const SIMDci8& value ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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, HasSize > > + storea( T1* address, const SIMDi16& 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, HasSize > > + storea( complex* address, const SIMDci16& value ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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, HasSize > > + storea( T1* address, const SIMDi32& 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, HasSize > > + storea( complex* address, const SIMDci32& value ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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, HasSize > > + storea( T1* address, const SIMDi64& 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, HasSize > > + storea( complex* address, const SIMDci64& value ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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& 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' values. +// \ingroup simd +// +// \param address The target address. +// \param value The 'complex' vector to be stored. +// \return void +// +// This function stores a vector of '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). +*/ +BLAZE_ALWAYS_INLINE void storea( complex* address, const SIMDcfloat& value ) noexcept +{ + BLAZE_STATIC_ASSERT ( sizeof( complex ) == 2UL*sizeof( float ) ); + BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" ); + +#if BLAZE_MIC_MODE + _mm512_store_ps( reinterpret_cast( address ), value.value ); +#elif BLAZE_AVX_MODE + _mm256_store_ps( reinterpret_cast( address ), value.value ); +#elif BLAZE_SSE_MODE + _mm_store_ps( reinterpret_cast( 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& 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' values. +// \ingroup simd +// +// \param address The target address. +// \param value The 'complex' vector to be stored. +// \return void +// +// This function stores a vector of '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). +*/ +BLAZE_ALWAYS_INLINE void storea( complex* address, const SIMDcdouble& value ) noexcept +{ + BLAZE_STATIC_ASSERT ( sizeof( complex ) == 2UL*sizeof( double ) ); + BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" ); + +#if BLAZE_MIC_MODE + _mm512_store_pd( reinterpret_cast( address ), value.value ); +#elif BLAZE_AVX_MODE + _mm256_store_pd( reinterpret_cast( address ), value.value ); +#elif BLAZE_SSE2_MODE + _mm_store_pd( reinterpret_cast( 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 +#include +#include +#include +#include +#include +#include +#include +#include + + +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, HasSize > > + storeu( T1* address, const SIMDi8& 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, HasSize > > + storeu( complex* address, const SIMDci8& value ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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, HasSize > > + storeu( T1* address, const SIMDi16& 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, HasSize > > + storeu( complex* address, const SIMDci16& value ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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, HasSize > > + storeu( T1* address, const SIMDi32& 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, HasSize > > + storeu( complex* address, const SIMDci32& value ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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, HasSize > > + storeu( T1* address, const SIMDi64& 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, HasSize > > + storeu( complex* address, const SIMDci64& value ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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& 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' values. +// \ingroup simd +// +// \param address The target address. +// \param value The 'complex' vector to be stored. +// \return void +// +// This function stores a vector of 'complex' 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* address, const SIMDcfloat& value ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( float ) ); + +#if BLAZE_MIC_MODE + _mm512_packstorelo_ps( reinterpret_cast( address ), value.value ); + _mm512_packstorehi_ps( reinterpret_cast( address+8UL ), value.value ); +#elif BLAZE_AVX_MODE + _mm256_storeu_ps( reinterpret_cast( address ), value.value ); +#elif BLAZE_SSE_MODE + _mm_storeu_ps( reinterpret_cast( 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& 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' values. +// \ingroup simd +// +// \param address The target address. +// \param value The 'complex' vector to be stored. +// \return void +// +// This function stores a vector of 'complex' 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* address, const SIMDcdouble& value ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 2UL*sizeof( double ) ); + +#if BLAZE_MIC_MODE + _mm512_packstorelo_pd( reinterpret_cast( address ), value.value ); + _mm512_packstorehi_pd( reinterpret_cast( address+4UL ), value.value ); +#elif BLAZE_AVX_MODE + _mm256_storeu_pd( reinterpret_cast( address ), value.value ); +#elif BLAZE_SSE2_MODE + _mm_storeu_pd( reinterpret_cast( 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, HasSize > > + stream( T1* address, const SIMDi8& 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, HasSize > > + stream( complex* address, const SIMDci8& value ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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, HasSize > > + stream( T1* address, const SIMDi16& 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, HasSize > > + stream( complex* address, const SIMDci16& value ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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, HasSize > > + stream( T1* address, const SIMDi32& 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, HasSize > > + stream( complex* address, const SIMDci32& value ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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, HasSize > > + stream( T1* address, const SIMDi64& 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, HasSize > > + stream( complex* address, const SIMDci64& value ) noexcept +{ + BLAZE_STATIC_ASSERT( sizeof( complex ) == 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& 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' values. +// \ingroup simd +// +// \param address The target address. +// \param value The 'complex' vector to be streamed. +// \return void +*/ +BLAZE_ALWAYS_INLINE void stream( complex* address, const SIMDcfloat& value ) noexcept +{ + BLAZE_STATIC_ASSERT ( sizeof( complex ) == 2UL*sizeof( float ) ); + BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" ); + +#if BLAZE_MIC_MODE + _mm512_storenr_ps( reinterpret_cast( address ), value.value ); +#elif BLAZE_AVX_MODE + _mm256_stream_ps( reinterpret_cast( address ), value.value ); +#elif BLAZE_SSE_MODE + _mm_stream_ps( reinterpret_cast( 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& 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' values. +// \ingroup simd +// +// \param address The target address. +// \param value The 'complex' vector to be streamed. +// \return void +*/ +BLAZE_ALWAYS_INLINE void stream( complex* address, const SIMDcdouble& value ) noexcept +{ + BLAZE_STATIC_ASSERT ( sizeof( complex ) == 2UL*sizeof( double ) ); + BLAZE_INTERNAL_ASSERT( checkAlignment( address ), "Invalid alignment detected" ); + +#if BLAZE_MIC_MODE + _mm512_storenr_pd( reinterpret_cast( address ), value.value ); +#elif BLAZE_AVX_MODE + _mm256_stream_pd( reinterpret_cast( address ), value.value ); +#elif BLAZE_SSE2_MODE + _mm_stream_pd( reinterpret_cast( 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 +#include +#include + + +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& a, const SIMDi8& 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& a, const SIMDi8& 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& a, const SIMDci8& 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& a, const SIMDi16& 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& a, const SIMDi16& 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& a, const SIMDci16& 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& a, const SIMDi32& 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& a, const SIMDi32& 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& a, const SIMDci32& 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& a, const SIMDi64& 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& a, const SIMDi64& 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& a, const SIMDci64& 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& a, const SIMDf32& 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& a, const SIMDf64& 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 +#include +#include + + +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& 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& 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 +#include +#include + + +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& 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& 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 + +#if BLAZE_OPENMP_PARALLEL_MODE +#include +#elif BLAZE_CPP_THREADS_PARALLEL_MODE || BLAZE_BOOST_THREADS_PARALLEL_MODE +#include +#else +#include +#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 + +#if BLAZE_OPENMP_PARALLEL_MODE +#include +#elif BLAZE_CPP_THREADS_PARALLEL_MODE || BLAZE_BOOST_THREADS_PARALLEL_MODE +#include +#else +#include +#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 + +#if BLAZE_OPENMP_PARALLEL_MODE +#include +#elif BLAZE_CPP_THREADS_PARALLEL_MODE || BLAZE_BOOST_THREADS_PARALLEL_MODE +#include +#else +#include +#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 +#include + + +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::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::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::~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::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::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 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 +#include + + +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::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::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::~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::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::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 A; + blaze::DynamicVector 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 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 + +#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 + +#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 +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Dense matrix SMP functions */ +//@{ +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline EnableIf_< IsDenseMatrix > + smpAssign( Matrix& lhs, const Matrix& rhs ); + +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline EnableIf_< IsDenseMatrix > + smpAddAssign( Matrix& lhs, const Matrix& rhs ); + +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline EnableIf_< IsDenseMatrix > + smpSubAssign( Matrix& lhs, const Matrix& 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 > + smpAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_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 > + smpAddAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_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 > + smpSubAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_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 +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Dense vector SMP functions */ +//@{ +template< typename VT1, bool TF1, typename VT2, bool TF2 > +inline EnableIf_< IsDenseVector > + smpAssign( Vector& lhs, const Vector& rhs ); + +template< typename VT1, bool TF1, typename VT2, bool TF2 > +inline EnableIf_< IsDenseVector > + smpAddAssign( Vector& lhs, const Vector& rhs ); + +template< typename VT1, bool TF1, typename VT2, bool TF2 > +inline EnableIf_< IsDenseVector > + smpSubAssign( Vector& lhs, const Vector& rhs ); + +template< typename VT1, bool TF1, typename VT2, bool TF2 > +inline EnableIf_< IsDenseVector > + smpMultAssign( Vector& lhs, const Vector& rhs ); + +template< typename VT1, bool TF1, typename VT2, bool TF2 > +inline EnableIf_< IsDenseVector > + smpDivAssign( Vector& lhs, const Vector& 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 > + smpAssign( Vector& lhs, const Vector& 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 > + smpAddAssign( Vector& lhs, const Vector& 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 > + smpSubAssign( Vector& lhs, const Vector& 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 > + smpMultAssign( Vector& lhs, const Vector& 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 > + smpDivAssign( Vector& lhs, const Vector& 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 +#include +#include +#include +#include + + +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 +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Sparse matrix SMP functions */ +//@{ +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline EnableIf_< IsSparseMatrix > + smpAssign( Matrix& lhs, const Matrix& rhs ); + +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline EnableIf_< IsSparseMatrix > + smpAddAssign( Matrix& lhs, const Matrix& rhs ); + +template< typename MT1, bool SO1, typename MT2, bool SO2 > +inline EnableIf_< IsSparseMatrix > + smpSubAssign( Matrix& lhs, const Matrix& 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 > + smpAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_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 > + smpAddAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_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 > + smpSubAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_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 +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Sparse vector SMP functions */ +//@{ +template< typename VT1, bool TF1, typename VT2, bool TF2 > +inline EnableIf_< IsSparseVector > + smpAssign( Vector& lhs, const Vector& rhs ); + +template< typename VT1, bool TF1, typename VT2, bool TF2 > +inline EnableIf_< IsSparseVector > + smpAddAssign( Vector& lhs, const Vector& rhs ); + +template< typename VT1, bool TF1, typename VT2, bool TF2 > +inline EnableIf_< IsSparseVector > + smpSubAssign( Vector& lhs, const Vector& rhs ); + +template< typename VT1, bool TF1, typename VT2, bool TF2 > +inline EnableIf_< IsSparseVector > + smpMultAssign( Vector& lhs, const Vector& 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 > + smpAssign( Vector& lhs, const Vector& 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 > + smpAddAssign( Vector& lhs, const Vector& 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 > + smpSubAssign( Vector& lhs, const Vector& 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 > + smpMultAssign( Vector& lhs, const Vector& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ AlignedTarget; + typedef SubmatrixExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame::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= (~lhs).rows() ) + continue; + + const size_t m( min( rowsPerThread, (~lhs).rows() - row ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + assign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + assign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + assign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else { + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + assign( target, submatrix( ~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& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ AlignedTarget; + typedef SubmatrixExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame::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= (~lhs).columns() ) + continue; + + const size_t n( min( colsPerThread, (~lhs).columns() - column ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + assign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + assign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + assign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else { + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + assign( target, submatrix( ~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& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ 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= (~lhs).rows() ) + continue; + + const size_t m( min( rowsPerThread, (~lhs).rows() - row ) ); + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + assign( target, submatrix( ~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& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ 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= (~lhs).columns() ) + continue; + + const size_t n( min( colsPerThread, (~lhs).columns() - column ) ); + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + assign( target, submatrix( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_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, IsSMPAssignable, IsSMPAssignable > > + smpAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ AlignedTarget; + typedef SubmatrixExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame::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= (~lhs).rows() ) + continue; + + const size_t m( min( rowsPerThread, (~lhs).rows() - row ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + addAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + addAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + addAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else { + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + addAssign( target, submatrix( ~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& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ AlignedTarget; + typedef SubmatrixExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame::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= (~lhs).columns() ) + continue; + + const size_t n( min( colsPerThread, (~lhs).columns() - column ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + addAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + addAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + addAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else { + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + addAssign( target, submatrix( ~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& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ 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= (~lhs).rows() ) + continue; + + const size_t m( min( rowsPerThread, (~lhs).rows() - row ) ); + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + addAssign( target, submatrix( ~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& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ 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= (~lhs).columns() ) + continue; + + const size_t n( min( colsPerThread, (~lhs).columns() - column ) ); + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + addAssign( target, submatrix( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpAddAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_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, IsSMPAssignable, IsSMPAssignable > > + smpAddAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ AlignedTarget; + typedef SubmatrixExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame::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= (~lhs).rows() ) + continue; + + const size_t m( min( rowsPerThread, (~lhs).rows() - row ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + subAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + subAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + subAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else { + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + subAssign( target, submatrix( ~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& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ AlignedTarget; + typedef SubmatrixExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame::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= (~lhs).columns() ) + continue; + + const size_t n( min( colsPerThread, (~lhs).columns() - column ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + subAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + subAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + subAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else { + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + subAssign( target, submatrix( ~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& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ 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= (~lhs).rows() ) + continue; + + const size_t m( min( rowsPerThread, (~lhs).rows() - row ) ); + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + subAssign( target, submatrix( ~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& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ 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= (~lhs).columns() ) + continue; + + const size_t n( min( colsPerThread, (~lhs).columns() - column ) ); + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + subAssign( target, submatrix( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpSubAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_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, IsSMPAssignable, IsSMPAssignable > > + smpSubAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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 > + smpMultAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ AlignedTarget; + typedef SubvectorExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame::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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + assign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + assign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + assign( target, subvector( ~rhs, index, size ) ); + } + else { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + assign( target, subvector( ~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& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ 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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + UnalignedTarget target( subvector( ~lhs, index, size ) ); + assign( target, subvector( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpAssign( Vector& lhs, const Vector& 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, IsSMPAssignable, IsSMPAssignable > > + smpAssign( Vector& lhs, const Vector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ AlignedTarget; + typedef SubvectorExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame::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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + addAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + addAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + addAssign( target, subvector( ~rhs, index, size ) ); + } + else { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + addAssign( target, subvector( ~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& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ 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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + UnalignedTarget target( subvector( ~lhs, index, size ) ); + addAssign( target, subvector( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpAddAssign( Vector& lhs, const Vector& 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, IsSMPAssignable, IsSMPAssignable > > + smpAddAssign( Vector& lhs, const Vector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ AlignedTarget; + typedef SubvectorExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame::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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + subAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + subAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + subAssign( target, subvector( ~rhs, index, size ) ); + } + else { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + subAssign( target, subvector( ~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& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ 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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + UnalignedTarget target( subvector( ~lhs, index, size ) ); + subAssign( target, subvector( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpSubAssign( Vector& lhs, const Vector& 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, IsSMPAssignable, IsSMPAssignable > > + smpSubAssign( Vector& lhs, const Vector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ AlignedTarget; + typedef SubvectorExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame::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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + multAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + multAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + multAssign( target, subvector( ~rhs, index, size ) ); + } + else { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + multAssign( target, subvector( ~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& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ 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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + UnalignedTarget target( subvector( ~lhs, index, size ) ); + multAssign( target, subvector( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpMultAssign( Vector& lhs, const Vector& 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, IsSMPAssignable, IsSMPAssignable > > + smpMultAssign( Vector& lhs, const Vector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ AlignedTarget; + typedef SubvectorExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame::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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + divAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + divAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + divAssign( target, subvector( ~rhs, index, size ) ); + } + else { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + divAssign( target, subvector( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpDivAssign( Vector& lhs, const Vector& 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, IsSMPAssignable, IsSMPAssignable > > + smpDivAssign( Vector& lhs, const Vector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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 +#include +#include +#include +#include +#include + + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ AlignedTarget; + typedef SubmatrixExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame::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= (~lhs).rows() ) + continue; + + const size_t m( min( rowsPerThread, (~lhs).rows() - row ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else { + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleAssign( target, submatrix( ~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& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ AlignedTarget; + typedef SubmatrixExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame::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= (~lhs).columns() ) + continue; + + const size_t n( min( colsPerThread, (~lhs).columns() - column ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else { + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleAssign( target, submatrix( ~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& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ 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= (~lhs).rows() ) + continue; + + const size_t m( min( rowsPerThread, (~lhs).rows() - row ) ); + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleAssign( target, submatrix( ~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& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ 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= (~lhs).columns() ) + continue; + + const size_t n( min( colsPerThread, (~lhs).columns() - column ) ); + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleAssign( target, submatrix( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_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, IsSMPAssignable, IsSMPAssignable > > + smpAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ AlignedTarget; + typedef SubmatrixExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame::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= (~lhs).rows() ) + continue; + + const size_t m( min( rowsPerThread, (~lhs).rows() - row ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleAddAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleAddAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleAddAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else { + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleAddAssign( target, submatrix( ~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& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ AlignedTarget; + typedef SubmatrixExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame::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= (~lhs).columns() ) + continue; + + const size_t n( min( colsPerThread, (~lhs).columns() - column ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleAddAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleAddAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleAddAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else { + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleAddAssign( target, submatrix( ~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& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ 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= (~lhs).rows() ) + continue; + + const size_t m( min( rowsPerThread, (~lhs).rows() - row ) ); + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleAddAssign( target, submatrix( ~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& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ 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= (~lhs).columns() ) + continue; + + const size_t n( min( colsPerThread, (~lhs).columns() - column ) ); + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleAddAssign( target, submatrix( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpAddAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_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, IsSMPAssignable, IsSMPAssignable > > + smpAddAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ AlignedTarget; + typedef SubmatrixExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame::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= (~lhs).rows() ) + continue; + + const size_t m( min( rowsPerThread, (~lhs).rows() - row ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleSubAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleSubAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleSubAssign( target, submatrix( ~rhs, row, 0UL, m, (~lhs).columns() ) ); + } + else { + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleSubAssign( target, submatrix( ~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& lhs, const DenseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ AlignedTarget; + typedef SubmatrixExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( MT1::simdEnabled && MT2::simdEnabled && IsSame::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= (~lhs).columns() ) + continue; + + const size_t n( min( colsPerThread, (~lhs).columns() - column ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleSubAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleSubAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleSubAssign( target, submatrix( ~rhs, 0UL, column, (~lhs).rows(), n ) ); + } + else { + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleSubAssign( target, submatrix( ~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& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ 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= (~lhs).rows() ) + continue; + + const size_t m( min( rowsPerThread, (~lhs).rows() - row ) ); + UnalignedTarget target( submatrix( ~lhs, row, 0UL, m, (~lhs).columns() ) ); + TheThreadBackend::scheduleSubAssign( target, submatrix( ~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& lhs, const SparseMatrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubmatrixExprTrait_ 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= (~lhs).columns() ) + continue; + + const size_t n( min( colsPerThread, (~lhs).columns() - column ) ); + UnalignedTarget target( submatrix( ~lhs, 0UL, column, (~lhs).rows(), n ) ); + TheThreadBackend::scheduleSubAssign( target, submatrix( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpSubAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_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, IsSMPAssignable, IsSMPAssignable > > + smpSubAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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 > + smpMultAssign( Matrix& lhs, const Matrix& rhs ) +{ + BLAZE_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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ AlignedTarget; + typedef SubvectorExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame::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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleAssign( target, subvector( ~rhs, index, size ) ); + } + else { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleAssign( target, subvector( ~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& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ 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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + UnalignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleAssign( target, subvector( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpAssign( Vector& lhs, const Vector& 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, IsSMPAssignable, IsSMPAssignable > > + smpAssign( Vector& lhs, const Vector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ AlignedTarget; + typedef SubvectorExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame::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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleAddAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleAddAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleAddAssign( target, subvector( ~rhs, index, size ) ); + } + else { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleAddAssign( target, subvector( ~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& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ 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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + UnalignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleAddAssign( target, subvector( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpAddAssign( Vector& lhs, const Vector& 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, IsSMPAssignable, IsSMPAssignable > > + smpAddAssign( Vector& lhs, const Vector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ AlignedTarget; + typedef SubvectorExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame::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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleSubAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleSubAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleSubAssign( target, subvector( ~rhs, index, size ) ); + } + else { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleSubAssign( target, subvector( ~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& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ 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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + UnalignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleSubAssign( target, subvector( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpSubAssign( Vector& lhs, const Vector& 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, IsSMPAssignable, IsSMPAssignable > > + smpSubAssign( Vector& lhs, const Vector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ AlignedTarget; + typedef SubvectorExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame::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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleMultAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleMultAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleMultAssign( target, subvector( ~rhs, index, size ) ); + } + else { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleMultAssign( target, subvector( ~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& lhs, const SparseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ 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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + UnalignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleMultAssign( target, subvector( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpMultAssign( Vector& lhs, const Vector& 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, IsSMPAssignable, IsSMPAssignable > > + smpMultAssign( Vector& lhs, const Vector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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& lhs, const DenseVector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_INTERNAL_ASSERT( isParallelSectionActive(), "Invalid call outside a parallel section" ); + + typedef ElementType_ ET1; + typedef ElementType_ ET2; + typedef SubvectorExprTrait_ AlignedTarget; + typedef SubvectorExprTrait_ UnalignedTarget; + + enum : size_t { SIMDSIZE = SIMDTrait< ElementType_ >::size }; + + const bool simdEnabled( VT1::simdEnabled && VT2::simdEnabled && IsSame::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= (~lhs).size() ) + continue; + + const size_t size( min( sizePerThread, (~lhs).size() - index ) ); + + if( simdEnabled && lhsAligned && rhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleDivAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && lhsAligned ) { + AlignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleDivAssign( target, subvector( ~rhs, index, size ) ); + } + else if( simdEnabled && rhsAligned ) { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleDivAssign( target, subvector( ~rhs, index, size ) ); + } + else { + UnalignedTarget target( subvector( ~lhs, index, size ) ); + TheThreadBackend::scheduleDivAssign( target, subvector( ~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 + , Or< Not< IsSMPAssignable > + , Not< IsSMPAssignable > > > > + smpDivAssign( Vector& lhs, const Vector& 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, IsSMPAssignable, IsSMPAssignable > > + smpDivAssign( Vector& lhs, const Vector& rhs ) +{ + BLAZE_FUNCTION_TRACE; + + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + BLAZE_CONSTRAINT_MUST_NOT_BE_SMP_ASSIGNABLE( ElementType_ ); + + 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 +#include +#include +#include +#include +#include + + +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 +# include +# include +#elif BLAZE_BOOST_THREADS_PARALLEL_MODE +# include +# include +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + + +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 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 ThreadBackend::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::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::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::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::scheduleAssign( Target& target, const Source& source ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_CONST( Target ); + threadpool_.schedule( Assigner( 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::scheduleAddAssign( Target& target, const Source& source ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_CONST( Target ); + threadpool_.schedule( AddAssigner( 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::scheduleSubAssign( Target& target, const Source& source ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_CONST( Target ); + threadpool_.schedule( SubAssigner( 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::scheduleMultAssign( Target& target, const Source& source ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_CONST( Target ); + threadpool_.schedule( MultAssigner( 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::scheduleDivAssign( Target& target, const Source& source ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_CONST( Target ); + threadpool_.schedule( DivAssigner( 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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 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 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::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 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 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 C( 2, 3, 4.0F ); // Directly, homogeneously initialized single precision dense 2x3 matrix + CompressedMatrix D( 3, 2 ); // Empty row-major sparse single precision matrix + + CompressedMatrix E( A ); // Creation of a new row-major matrix as a copy of A + CompressedMatrix 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, SO > +{ + private: + //**Type definitions**************************************************************************** + typedef ValueIndexPair 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 This; //!< Type of this CompressedMatrix instance. + typedef SparseMatrix BaseType; //!< Base type of this CompressedMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef CompressedMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef CompressedMatrix 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 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 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::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& nonzeros ); + inline CompressedMatrix( const CompressedMatrix& sm ); + inline CompressedMatrix( CompressedMatrix&& sm ) noexcept; + template< typename MT, bool SO2 > inline CompressedMatrix( const DenseMatrix& dm ); + template< typename MT, bool SO2 > inline CompressedMatrix( const SparseMatrix& 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& rhs ); + template< typename MT, bool SO2 > inline CompressedMatrix& operator= ( const SparseMatrix& rhs ); + template< typename MT, bool SO2 > inline CompressedMatrix& operator+=( const Matrix& rhs ); + template< typename MT, bool SO2 > inline CompressedMatrix& operator-=( const Matrix& rhs ); + template< typename MT, bool SO2 > inline CompressedMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, CompressedMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& rhs ); + template< typename MT > inline void assign ( const SparseMatrix& rhs ); + template< typename MT > inline void assign ( const SparseMatrix& rhs ); + template< typename MT, bool SO2 > inline void addAssign( const DenseMatrix& rhs ); + template< typename MT, bool SO2 > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT, bool SO2 > inline void subAssign( const DenseMatrix& rhs ); + template< typename MT, bool SO2 > inline void subAssign( const SparseMatrix& 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::zero_ = Type(); + + + + +//================================================================================================= +// +// CONSTRUCTORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief The default constructor for CompressedMatrix. +*/ +template< typename Type // Data type of the sparse matrix + , bool SO > // Storage order +inline CompressedMatrix::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::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::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( 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::CompressedMatrix( size_t m, size_t n, const std::vector& 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::const_iterator it=nonzeros.begin(); it!=nonzeros.end(); ++it ) + newCapacity += *it; + + begin_[0UL] = end_[0UL] = allocate( newCapacity ); + for( size_t i=0UL; i // Storage order +inline CompressedMatrix::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( nonzeros ); + for( size_t i=0UL; i // Storage order +inline CompressedMatrix::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::CompressedMatrix( const DenseMatrix& 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::CompressedMatrix( const SparseMatrix& 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( nonzeros ); + for( size_t i=0UL; i // Storage order +inline CompressedMatrix::~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::Reference + CompressedMatrix::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::ConstReference + CompressedMatrix::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::Reference + CompressedMatrix::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::ConstReference + CompressedMatrix::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::Iterator + CompressedMatrix::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::ConstIterator + CompressedMatrix::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::ConstIterator + CompressedMatrix::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::Iterator + CompressedMatrix::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::ConstIterator + CompressedMatrix::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::ConstIterator + CompressedMatrix::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& + CompressedMatrix::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( nonzeros ); + for( size_t i=0UL; i // Storage order +inline CompressedMatrix& + CompressedMatrix::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& + CompressedMatrix::operator=( const DenseMatrix& 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& + CompressedMatrix::operator=( const SparseMatrix& 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& + CompressedMatrix::operator+=( const Matrix& 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& CompressedMatrix::operator-=( const Matrix& 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& + CompressedMatrix::operator*=( const Matrix& 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, CompressedMatrix >& + CompressedMatrix::operator*=( Other rhs ) +{ + for( size_t i=0UL; ivalue_ *= 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, CompressedMatrix >& + CompressedMatrix::operator/=( Other rhs ) +{ + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + typedef DivTrait_ DT; + typedef If_< IsNumeric
, DT, Other > Tmp; + + // Depending on the two involved data types, an integer division is applied or a + // floating point division is selected. + if( IsNumeric
::value && IsFloatingPoint
::value ) { + const Tmp tmp( Tmp(1)/static_cast( rhs ) ); + for( size_t i=0UL; ivalue_ *= tmp; + } + } + else { + for( size_t i=0UL; ivalue_ /= 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::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::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::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::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::nonZeros() const +{ + size_t nonzeros( 0UL ); + + for( size_t i=0UL; i // Storage order +inline size_t CompressedMatrix::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::reset() +{ + for( size_t i=0UL; i // Storage order +inline void CompressedMatrix::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::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::Iterator + CompressedMatrix::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::Iterator + CompressedMatrix::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::Iterator + CompressedMatrix::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( newCapacity ); + + for( size_t k=0UL; kvalue_ = 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::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::Iterator + CompressedMatrix::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::Iterator + CompressedMatrix::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::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_ ) + { + end_[m] = end_[m_]; + + if( !preserve ) { + for( size_t i=0UL; i= 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::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::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( 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( newCapacity ); + newEnd [m_ ] = newBegin[0UL]+newCapacity; + + for( size_t k=0UL; ki; --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( 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::trim() +{ + for( size_t i=0UL; i // Storage order +inline void CompressedMatrix::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& CompressedMatrix::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& CompressedMatrix::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& CompressedMatrix::scale( const Other& scalar ) +{ + for( size_t i=0UL; ivalue_ *= 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& CompressedMatrix::scaleDiagonal( Other scalar ) +{ + const size_t size( blaze::min( m_, n_ ) ); + + for( size_t i=0UL; iindex_ == 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::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::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::reserveElements( size_t nonzeros ) +{ + Iterator* newBegin = new Iterator[2UL*capacity_+2UL]; + Iterator* newEnd = newBegin+capacity_+1UL; + + newBegin[0UL] = allocate( nonzeros ); + + for( size_t k=0UL; k // Storage order +inline typename CompressedMatrix::Iterator + CompressedMatrix::find( size_t i, size_t j ) +{ + return const_cast( const_cast( *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::ConstIterator + CompressedMatrix::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::Iterator + CompressedMatrix::lowerBound( size_t i, size_t j ) +{ + return const_cast( const_cast( *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::ConstIterator + CompressedMatrix::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::Iterator + CompressedMatrix::upperBound( size_t i, size_t j ) +{ + return const_cast( const_cast( *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::ConstIterator + CompressedMatrix::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 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::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::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::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::assign( const DenseMatrix& 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::value ) + ?( IsStrictlyUpper::value ? i+1UL : i ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::value ? i : i+1UL ) + :( n_ ) ); + + for( size_t j=jbegin; jvalue_ = (~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::assign( const SparseMatrix& 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 // Storage order +template< typename MT > // Type of the right-hand side sparse matrix +inline void CompressedMatrix::assign( const SparseMatrix& 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_ RhsIterator; + + // Counting the number of elements per row + std::vector rowLengths( m_, 0UL ); + for( size_t j=0UL; jindex()]; + } + + // Resizing the sparse matrix + for( size_t i=0UL; iindex(), 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::addAssign( const DenseMatrix& 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::addAssign( const SparseMatrix& 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::subAssign( const DenseMatrix& 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::subAssign( const SparseMatrix& 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 : public SparseMatrix< CompressedMatrix, true > +{ + private: + //**Type definitions**************************************************************************** + typedef ValueIndexPair 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 This; //!< Type of this CompressedMatrix instance. + typedef SparseMatrix BaseType; //!< Base type of this CompressedMatrix instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef CompressedMatrix OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef CompressedMatrix 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 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 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::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& nonzeros ); + inline CompressedMatrix( const CompressedMatrix& sm ); + inline CompressedMatrix( CompressedMatrix&& sm ) noexcept; + template< typename MT, bool SO > inline CompressedMatrix( const DenseMatrix& dm ); + template< typename MT, bool SO > inline CompressedMatrix( const SparseMatrix& 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& rhs ); + template< typename MT, bool SO > inline CompressedMatrix& operator= ( const SparseMatrix& rhs ); + template< typename MT, bool SO > inline CompressedMatrix& operator+=( const Matrix& rhs ); + template< typename MT, bool SO > inline CompressedMatrix& operator-=( const Matrix& rhs ); + template< typename MT, bool SO > inline CompressedMatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, CompressedMatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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& rhs ); + template< typename MT > inline void assign ( const SparseMatrix& rhs ); + template< typename MT > inline void assign ( const SparseMatrix& rhs ); + template< typename MT, bool SO > inline void addAssign( const DenseMatrix& rhs ); + template< typename MT, bool SO > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT, bool SO > inline void subAssign( const DenseMatrix& rhs ); + template< typename MT, bool SO > inline void subAssign( const SparseMatrix& 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::zero_ = Type(); + + + + +//================================================================================================= +// +// CONSTRUCTORS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief The default constructor for CompressedMatrix. +*/ +template< typename Type > // Data type of the sparse matrix +inline CompressedMatrix::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::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::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( 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::CompressedMatrix( size_t m, size_t n, const std::vector& 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::const_iterator it=nonzeros.begin(); it!=nonzeros.end(); ++it ) + newCapacity += *it; + + begin_[0UL] = end_[0UL] = allocate( newCapacity ); + for( size_t j=0UL; j // Data type of the sparse matrix +inline CompressedMatrix::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( nonzeros ); + for( size_t j=0UL; j // Data type of the sparse matrix +inline CompressedMatrix::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::CompressedMatrix( const DenseMatrix& 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::CompressedMatrix( const SparseMatrix& 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( nonzeros ); + for( size_t j=0UL; j // Data type of the sparse matrix +inline CompressedMatrix::~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::Reference + CompressedMatrix::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::ConstReference + CompressedMatrix::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::Reference + CompressedMatrix::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::ConstReference + CompressedMatrix::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::Iterator + CompressedMatrix::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::ConstIterator + CompressedMatrix::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::ConstIterator + CompressedMatrix::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::Iterator + CompressedMatrix::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::ConstIterator + CompressedMatrix::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::ConstIterator + CompressedMatrix::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& + CompressedMatrix::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( nonzeros ); + for( size_t j=0UL; j // Data type of the sparse matrix +inline CompressedMatrix& + CompressedMatrix::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& + CompressedMatrix::operator=( const DenseMatrix& 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& + CompressedMatrix::operator=( const SparseMatrix& 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& CompressedMatrix::operator+=( const Matrix& 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& CompressedMatrix::operator-=( const Matrix& 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& + CompressedMatrix::operator*=( const Matrix& 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, CompressedMatrix >& + CompressedMatrix::operator*=( Other rhs ) +{ + for( size_t j=0UL; jvalue_ *= 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, CompressedMatrix >& + CompressedMatrix::operator/=( Other rhs ) +{ + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + typedef DivTrait_ DT; + typedef If_< IsNumeric
, DT, Other > Tmp; + + // Depending on the two involved data types, an integer division is applied or a + // floating point division is selected. + if( IsNumeric
::value && IsFloatingPoint
::value ) { + const Tmp tmp( Tmp(1)/static_cast( rhs ) ); + for( size_t j=0UL; jvalue_ *= tmp; + } + } + else { + for( size_t j=0UL; jvalue_ /= 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::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::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::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::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::nonZeros() const +{ + size_t nonzeros( 0UL ); + + for( size_t j=0UL; j // Data type of the sparse matrix +inline size_t CompressedMatrix::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::reset() +{ + for( size_t j=0UL; j // Data type of the sparse matrix +inline void CompressedMatrix::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::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::Iterator + CompressedMatrix::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::Iterator + CompressedMatrix::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::Iterator + CompressedMatrix::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( newCapacity ); + + for( size_t k=0UL; kvalue_ = 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::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::Iterator + CompressedMatrix::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::Iterator + CompressedMatrix::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::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_ ) + { + end_[n] = end_[n_]; + + if( !preserve ) { + for( size_t j=0UL; j= 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::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::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( 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( newCapacity ); + newEnd [n_ ] = newBegin[0UL]+newCapacity; + + for( size_t k=0UL; kj; --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( 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::trim() +{ + for( size_t j=0UL; j // Data type of the sparse matrix +void CompressedMatrix::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& CompressedMatrix::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& CompressedMatrix::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& CompressedMatrix::scale( const Other& scalar ) +{ + for( size_t j=0UL; jvalue_ *= 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& CompressedMatrix::scaleDiagonal( Other scalar ) +{ + const size_t size( blaze::min( m_, n_ ) ); + + for( size_t j=0UL; jindex_ == 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::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::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::reserveElements( size_t nonzeros ) +{ + Iterator* newBegin = new Iterator[2UL*capacity_+2UL]; + Iterator* newEnd = newBegin+capacity_+1UL; + + newBegin[0UL] = allocate( nonzeros ); + + for( size_t k=0UL; k // Data type of the sparse matrix +inline typename CompressedMatrix::Iterator + CompressedMatrix::find( size_t i, size_t j ) +{ + return const_cast( const_cast( *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::ConstIterator + CompressedMatrix::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::Iterator + CompressedMatrix::lowerBound( size_t i, size_t j ) +{ + return const_cast( const_cast( *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::ConstIterator + CompressedMatrix::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::Iterator + CompressedMatrix::upperBound( size_t i, size_t j ) +{ + return const_cast( const_cast( *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::ConstIterator + CompressedMatrix::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 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::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::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::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::assign( const DenseMatrix& 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::value ) + ?( IsStrictlyLower::value ? j+1UL : j ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::value ? j : j+1UL ) + :( m_ ) ); + + for( size_t i=ibegin; ivalue_ = (~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::assign( const SparseMatrix& 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 // Data type of the sparse matrix +template< typename MT > // Type of the right-hand side sparse matrix +inline void CompressedMatrix::assign( const SparseMatrix& 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_ RhsIterator; + + // Counting the number of elements per column + std::vector columnLengths( n_, 0UL ); + for( size_t i=0UL; iindex()]; + } + + // Resizing the sparse matrix + for( size_t j=0UL; jindex(), 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::addAssign( const DenseMatrix& 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::addAssign( const SparseMatrix& 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::subAssign( const DenseMatrix& 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::subAssign( const SparseMatrix& 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& m ); + +template< typename Type, bool SO > +inline void reset( CompressedMatrix& m, size_t i ); + +template< typename Type, bool SO > +inline void clear( CompressedMatrix& m ); + +template< typename Type, bool SO > +inline bool isDefault( const CompressedMatrix& m ); + +template< typename Type, bool SO > +inline bool isIntact( const CompressedMatrix& m ); + +template< typename Type, bool SO > +inline void swap( CompressedMatrix& a, CompressedMatrix& 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& 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& 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& 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 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& 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 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& 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& a, CompressedMatrix& b ) noexcept +{ + a.swap( b ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool SO > +struct IsResizable< CompressedMatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ADDTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO, typename T2, size_t M, size_t N > +struct AddTrait< CompressedMatrix, StaticMatrix > +{ + using Type = StaticMatrix< AddTrait_, M, N, SO >; +}; + +template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 > +struct AddTrait< CompressedMatrix, StaticMatrix > +{ + using Type = StaticMatrix< AddTrait_, M, N, SO2 >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2 > +struct AddTrait< StaticMatrix, CompressedMatrix > +{ + using Type = StaticMatrix< AddTrait_, M, N, SO >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 > +struct AddTrait< StaticMatrix, CompressedMatrix > +{ + using Type = StaticMatrix< AddTrait_, M, N, SO1 >; +}; + +template< typename T1, bool SO, typename T2, size_t M, size_t N > +struct AddTrait< CompressedMatrix, HybridMatrix > +{ + using Type = HybridMatrix< AddTrait_, M, N, SO >; +}; + +template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 > +struct AddTrait< CompressedMatrix, HybridMatrix > +{ + using Type = HybridMatrix< AddTrait_, M, N, SO2 >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2 > +struct AddTrait< HybridMatrix, CompressedMatrix > +{ + using Type = HybridMatrix< AddTrait_, M, N, SO >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 > +struct AddTrait< HybridMatrix, CompressedMatrix > +{ + using Type = HybridMatrix< AddTrait_, M, N, SO1 >; +}; + +template< typename T1, bool SO, typename T2 > +struct AddTrait< CompressedMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< AddTrait_, SO >; +}; + +template< typename T1, bool SO1, typename T2, bool SO2 > +struct AddTrait< CompressedMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< AddTrait_, SO2 >; +}; + +template< typename T1, bool SO, typename T2 > +struct AddTrait< DynamicMatrix, CompressedMatrix > +{ + using Type = DynamicMatrix< AddTrait_, SO >; +}; + +template< typename T1, bool SO1, typename T2, bool SO2 > +struct AddTrait< DynamicMatrix, CompressedMatrix > +{ + using Type = DynamicMatrix< AddTrait_, SO1 >; +}; + +template< typename T1, bool SO, typename T2, bool AF, bool PF > +struct AddTrait< CompressedMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< AddTrait_, SO >; +}; + +template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 > +struct AddTrait< CompressedMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< AddTrait_, SO2 >; +}; + +template< typename T1, bool AF, bool PF, bool SO, typename T2 > +struct AddTrait< CustomMatrix, CompressedMatrix > +{ + using Type = DynamicMatrix< AddTrait_, SO >; +}; + +template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 > +struct AddTrait< CustomMatrix, CompressedMatrix > +{ + using Type = DynamicMatrix< AddTrait_, SO1 >; +}; + +template< typename T1, bool SO, typename T2 > +struct AddTrait< CompressedMatrix, CompressedMatrix > +{ + using Type = CompressedMatrix< AddTrait_, SO >; +}; + +template< typename T1, bool SO1, typename T2, bool SO2 > +struct AddTrait< CompressedMatrix, CompressedMatrix > +{ + using Type = CompressedMatrix< AddTrait_, false >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO, typename T2, size_t M, size_t N > +struct SubTrait< CompressedMatrix, StaticMatrix > +{ + using Type = StaticMatrix< SubTrait_, M, N, SO >; +}; + +template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 > +struct SubTrait< CompressedMatrix, StaticMatrix > +{ + using Type = StaticMatrix< SubTrait_, M, N, SO2 >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2 > +struct SubTrait< StaticMatrix, CompressedMatrix > +{ + using Type = StaticMatrix< SubTrait_, M, N, SO >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 > +struct SubTrait< StaticMatrix, CompressedMatrix > +{ + using Type = StaticMatrix< SubTrait_, M, N, SO1 >; +}; + +template< typename T1, bool SO, typename T2, size_t M, size_t N > +struct SubTrait< CompressedMatrix, HybridMatrix > +{ + using Type = HybridMatrix< SubTrait_, M, N, SO >; +}; + +template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 > +struct SubTrait< CompressedMatrix, HybridMatrix > +{ + using Type = HybridMatrix< SubTrait_, M, N, SO2 >; +}; + +template< typename T1, size_t M, size_t N, bool SO, typename T2 > +struct SubTrait< HybridMatrix, CompressedMatrix > +{ + using Type = HybridMatrix< SubTrait_, M, N, SO >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 > +struct SubTrait< HybridMatrix, CompressedMatrix > +{ + using Type = HybridMatrix< SubTrait_, M, N, SO1 >; +}; + +template< typename T1, bool SO, typename T2 > +struct SubTrait< CompressedMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< SubTrait_, SO >; +}; + +template< typename T1, bool SO1, typename T2, bool SO2 > +struct SubTrait< CompressedMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< SubTrait_, SO2 >; +}; + +template< typename T1, bool SO, typename T2 > +struct SubTrait< DynamicMatrix, CompressedMatrix > +{ + using Type = DynamicMatrix< SubTrait_, SO >; +}; + +template< typename T1, bool SO1, typename T2, bool SO2 > +struct SubTrait< DynamicMatrix, CompressedMatrix > +{ + using Type = DynamicMatrix< SubTrait_, SO1 >; +}; + +template< typename T1, bool SO, typename T2, bool AF, bool PF > +struct SubTrait< CompressedMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< SubTrait_, SO >; +}; + +template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 > +struct SubTrait< CompressedMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< SubTrait_, SO2 >; +}; + +template< typename T1, bool AF, bool PF, bool SO, typename T2 > +struct SubTrait< CustomMatrix, CompressedMatrix > +{ + using Type = DynamicMatrix< SubTrait_, SO >; +}; + +template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 > +struct SubTrait< CustomMatrix, CompressedMatrix > +{ + using Type = DynamicMatrix< SubTrait_, SO1 >; +}; + +template< typename T1, bool SO, typename T2 > +struct SubTrait< CompressedMatrix, CompressedMatrix > +{ + using Type = CompressedMatrix< SubTrait_ , SO >; +}; + +template< typename T1, bool SO1, typename T2, bool SO2 > +struct SubTrait< CompressedMatrix, CompressedMatrix > +{ + using Type = CompressedMatrix< SubTrait_ , false >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO, typename T2 > +struct MultTrait< CompressedMatrix, T2, EnableIf_< IsNumeric > > +{ + using Type = CompressedMatrix< MultTrait_, SO >; +}; + +template< typename T1, typename T2, bool SO > +struct MultTrait< T1, CompressedMatrix, EnableIf_< IsNumeric > > +{ + using Type = CompressedMatrix< MultTrait_, SO >; +}; + +template< typename T1, bool SO, typename T2, size_t N > +struct MultTrait< CompressedMatrix, StaticVector > +{ + using Type = DynamicVector< MultTrait_, false >; +}; + +template< typename T1, size_t N, typename T2, bool SO > +struct MultTrait< StaticVector, CompressedMatrix > +{ + using Type = DynamicVector< MultTrait_, true >; +}; + +template< typename T1, bool SO, typename T2, size_t N > +struct MultTrait< CompressedMatrix, HybridVector > +{ + using Type = DynamicVector< MultTrait_, false >; +}; + +template< typename T1, size_t N, typename T2, bool SO > +struct MultTrait< HybridVector, CompressedMatrix > +{ + using Type = DynamicVector< MultTrait_, true >; +}; + +template< typename T1, bool SO, typename T2 > +struct MultTrait< CompressedMatrix, DynamicVector > +{ + using Type = DynamicVector< MultTrait_, false >; +}; + +template< typename T1, typename T2, bool SO > +struct MultTrait< DynamicVector, CompressedMatrix > +{ + using Type = DynamicVector< MultTrait_, true >; +}; + +template< typename T1, bool SO, typename T2, bool AF, bool PF > +struct MultTrait< CompressedMatrix, CustomVector > +{ + using Type = DynamicVector< MultTrait_, false >; +}; + +template< typename T1, bool AF, bool PF, typename T2, bool SO > +struct MultTrait< CustomVector, CompressedMatrix > +{ + using Type = DynamicVector< MultTrait_, true >; +}; + +template< typename T1, bool SO, typename T2 > +struct MultTrait< CompressedMatrix, CompressedVector > +{ + using Type = CompressedVector< MultTrait_, false >; +}; + +template< typename T1, typename T2, bool SO > +struct MultTrait< CompressedVector, CompressedMatrix > +{ + using Type = CompressedVector< MultTrait_, true >; +}; + +template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 > +struct MultTrait< CompressedMatrix, StaticMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 > +struct MultTrait< StaticMatrix, CompressedMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, bool SO1, typename T2, size_t M, size_t N, bool SO2 > +struct MultTrait< CompressedMatrix, HybridMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, size_t M, size_t N, bool SO1, typename T2, bool SO2 > +struct MultTrait< HybridMatrix, CompressedMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, bool SO1, typename T2, bool SO2 > +struct MultTrait< CompressedMatrix, DynamicMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, bool SO1, typename T2, bool SO2 > +struct MultTrait< DynamicMatrix, CompressedMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, bool SO1, typename T2, bool AF, bool PF, bool SO2 > +struct MultTrait< CompressedMatrix, CustomMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, bool AF, bool PF, bool SO1, typename T2, bool SO2 > +struct MultTrait< CustomMatrix, CompressedMatrix > +{ + using Type = DynamicMatrix< MultTrait_, SO1 >; +}; + +template< typename T1, bool SO1, typename T2, bool SO2 > +struct MultTrait< CompressedMatrix, CompressedMatrix > +{ + using Type = CompressedMatrix< MultTrait_, SO1 >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO, typename T2 > +struct DivTrait< CompressedMatrix, T2, EnableIf_< IsNumeric > > +{ + using Type = CompressedMatrix< DivTrait_, SO >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MATHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO, typename T2 > +struct MathTrait< CompressedMatrix, CompressedMatrix > +{ + using HighType = CompressedMatrix< typename MathTrait::HighType, SO >; + using LowType = CompressedMatrix< typename MathTrait::LowType , SO >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO > +struct SubmatrixTrait< CompressedMatrix > +{ + using Type = CompressedMatrix; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO > +struct RowTrait< CompressedMatrix > +{ + using Type = CompressedVector; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool SO > +struct ColumnTrait< CompressedMatrix > +{ + using Type = CompressedVector; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 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::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 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 b( 2 ); // Empty sparse vector + DynamicVector c( 2, 2.0F ); // Directly, homogeneously initialized dense vector + CompressedVector d; // Default constructed dynamic vector + CompressedMatrix 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, TF > +{ + private: + //**Type definitions**************************************************************************** + typedef ValueIndexPair 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 This; //!< Type of this CompressedVector instance. + typedef SparseVector BaseType; //!< Base type of this CompressedVector instance. + typedef This ResultType; //!< Result type for expression template evaluations. + typedef CompressedVector 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 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 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::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& dv ); + template< typename VT > inline CompressedVector( const SparseVector& 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& rhs ); + template< typename VT > inline CompressedVector& operator= ( const SparseVector& rhs ); + template< typename VT > inline CompressedVector& operator+=( const Vector& rhs ); + template< typename VT > inline CompressedVector& operator-=( const Vector& rhs ); + template< typename VT > inline CompressedVector& operator*=( const DenseVector& rhs ); + template< typename VT > inline CompressedVector& operator*=( const SparseVector& rhs ); + template< typename VT > inline CompressedVector& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, CompressedVector >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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 & rhs ); + template< typename VT > inline void assign ( const SparseVector& rhs ); + template< typename VT > inline void addAssign ( const DenseVector & rhs ); + template< typename VT > inline void addAssign ( const SparseVector& rhs ); + template< typename VT > inline void subAssign ( const DenseVector & rhs ); + template< typename VT > inline void subAssign ( const SparseVector& rhs ); + template< typename VT > inline void multAssign( const DenseVector & rhs ); + template< typename VT > inline void divAssign ( const DenseVector & 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::zero_ = Type(); + + + + +//================================================================================================= +// +// CONSTRUCTORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief The default constructor for CompressedVector. +*/ +template< typename Type // Data type of the vector + , bool TF > // Transpose flag +inline CompressedVector::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::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::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( 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::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( 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::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::CompressedVector( const DenseVector& 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::CompressedVector( const SparseVector& sv ) + : size_ ( (~sv).size() ) // The current size/dimension of the compressed vector + , capacity_( (~sv).nonZeros() ) // The maximum capacity of the compressed vector + , begin_ ( allocate( 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::~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::Reference + CompressedVector::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::ConstReference + CompressedVector::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::Reference + CompressedVector::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::ConstReference + CompressedVector::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::Iterator CompressedVector::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::ConstIterator + CompressedVector::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::ConstIterator + CompressedVector::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::Iterator CompressedVector::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::ConstIterator + CompressedVector::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::ConstIterator + CompressedVector::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& + CompressedVector::operator=( const CompressedVector& rhs ) +{ + if( &rhs == this ) return *this; + + const size_t nonzeros( rhs.nonZeros() ); + + if( nonzeros > capacity_ ) { + Iterator newBegin( allocate( 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& + CompressedVector::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& + CompressedVector::operator=( const DenseVector& 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& + CompressedVector::operator=( const SparseVector& 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& CompressedVector::operator+=( const Vector& 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& CompressedVector::operator-=( const Vector& 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& + CompressedVector::operator*=( const DenseVector& 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_ 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& + CompressedVector::operator*=( const SparseVector& 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& CompressedVector::operator/=( const DenseVector& 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_ 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, CompressedVector >& + CompressedVector::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, CompressedVector >& + CompressedVector::operator/=( Other rhs ) +{ + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + typedef DivTrait_ DT; + typedef If_< IsNumeric
, DT, Other > Tmp; + + // Depending on the two involved data types, an integer division is applied or a + // floating point division is selected. + if( IsNumeric
::value && IsFloatingPoint
::value ) { + const Tmp tmp( Tmp(1)/static_cast( 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::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::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::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::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::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::Iterator + CompressedVector::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::Iterator + CompressedVector::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::Iterator + CompressedVector::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( 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::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::Iterator CompressedVector::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::Iterator + CompressedVector::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::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::reserve( size_t n ) +{ + if( n > capacity_ ) { + const size_t newCapacity( n ); + + // Allocating a new data and index array + Iterator newBegin = allocate( 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& CompressedVector::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::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::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::Iterator CompressedVector::find( size_t index ) +{ + return const_cast( const_cast( *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::ConstIterator CompressedVector::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::Iterator + CompressedVector::lowerBound( size_t index ) +{ + return const_cast( const_cast( *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::ConstIterator + CompressedVector::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::Iterator + CompressedVector::upperBound( size_t index ) +{ + return const_cast( const_cast( *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::ConstIterator + CompressedVector::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::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::canAlias( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::isAliased( const Other* alias ) const noexcept +{ + return static_cast( this ) == static_cast( 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::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::assign( const DenseVector& 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; ivalue_ = (~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::assign( const SparseVector& 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_ 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::addAssign( const DenseVector& rhs ) +{ + typedef AddTrait_< This, ResultType_ > 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_ ); + + 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::addAssign( const SparseVector& 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::subAssign( const DenseVector& rhs ) +{ + typedef SubTrait_< This, ResultType_ > 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_ ); + + 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::subAssign( const SparseVector& 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::multAssign( const DenseVector& 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::divAssign( const DenseVector& 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& v ); + +template< typename Type, bool TF > +inline void clear( CompressedVector& v ); + +template< typename Type, bool TF > +inline bool isDefault( const CompressedVector& v ); + +template< typename Type, bool TF > +inline bool isIntact( const CompressedVector& v ) noexcept; + +template< typename Type, bool TF > +inline void swap( CompressedVector& a, CompressedVector& 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& 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& 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 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& 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 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& 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& a, CompressedVector& b ) noexcept +{ + a.swap( b ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISRESIZABLE SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T, bool TF > +struct IsResizable< CompressedVector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ADDTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool TF, typename T2, size_t N > +struct AddTrait< CompressedVector, StaticVector > +{ + using Type = StaticVector< AddTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct AddTrait< StaticVector, CompressedVector > +{ + using Type = StaticVector< AddTrait_, N, TF >; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct AddTrait< CompressedVector, HybridVector > +{ + using Type = HybridVector< AddTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct AddTrait< HybridVector, CompressedVector > +{ + using Type = HybridVector< AddTrait_, N, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct AddTrait< CompressedVector, DynamicVector > +{ + using Type = DynamicVector< AddTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct AddTrait< DynamicVector, CompressedVector > +{ + using Type = DynamicVector< AddTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2, bool AF, bool PF > +struct AddTrait< CompressedVector, CustomVector > +{ + using Type = DynamicVector< AddTrait_, TF >; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2 > +struct AddTrait< CustomVector, CompressedVector > +{ + using Type = DynamicVector< AddTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct AddTrait< CompressedVector, CompressedVector > +{ + using Type = CompressedVector< AddTrait_, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool TF, typename T2, size_t N > +struct SubTrait< CompressedVector, StaticVector > +{ + using Type = StaticVector< SubTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct SubTrait< StaticVector, CompressedVector > +{ + using Type = StaticVector< SubTrait_, N, TF >; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct SubTrait< CompressedVector, HybridVector > +{ + using Type = HybridVector< SubTrait_, N, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct SubTrait< HybridVector, CompressedVector > +{ + using Type = HybridVector< SubTrait_, N, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct SubTrait< CompressedVector, DynamicVector > +{ + using Type = DynamicVector< SubTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct SubTrait< DynamicVector, CompressedVector > +{ + using Type = DynamicVector< SubTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2, bool AF, bool PF > +struct SubTrait< CompressedVector, CustomVector > +{ + using Type = DynamicVector< SubTrait_, TF >; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2 > +struct SubTrait< CustomVector, CompressedVector > +{ + using Type = DynamicVector< SubTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct SubTrait< CompressedVector, CompressedVector > +{ + using Type = CompressedVector< SubTrait_, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool TF, typename T2 > +struct MultTrait< CompressedVector, T2, EnableIf_< IsNumeric > > +{ + using Type = CompressedVector< MultTrait_, TF >; +}; + +template< typename T1, typename T2, bool TF > +struct MultTrait< T1, CompressedVector, EnableIf_< IsNumeric > > +{ + using Type = CompressedVector< MultTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct MultTrait< CompressedVector, StaticVector > +{ + using Type = CompressedVector< MultTrait_, TF >; +}; + +template< typename T1, typename T2, size_t N > +struct MultTrait< CompressedVector, StaticVector > +{ + using Type = CompressedMatrix< MultTrait_, true >; +}; + +template< typename T1, typename T2, size_t N > +struct MultTrait< CompressedVector, StaticVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct MultTrait< StaticVector, CompressedVector > +{ + using Type = CompressedVector< MultTrait_, TF >; +}; + +template< typename T1, size_t N, typename T2 > +struct MultTrait< StaticVector, CompressedVector > +{ + using Type = CompressedMatrix< MultTrait_, false >; +}; + +template< typename T1, size_t N, typename T2 > +struct MultTrait< StaticVector, CompressedVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct MultTrait< CompressedVector, HybridVector > +{ + using Type = CompressedVector< MultTrait_, TF >; +}; + +template< typename T1, typename T2, size_t N > +struct MultTrait< CompressedVector, HybridVector > +{ + using Type = CompressedMatrix< MultTrait_, true >; +}; + +template< typename T1, typename T2, size_t N > +struct MultTrait< CompressedVector, HybridVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct MultTrait< HybridVector, CompressedVector > +{ + using Type = CompressedVector< MultTrait_, TF >; +}; + +template< typename T1, size_t N, typename T2 > +struct MultTrait< HybridVector, CompressedVector > +{ + using Type = CompressedMatrix< MultTrait_, false >; +}; + +template< typename T1, size_t N, typename T2 > +struct MultTrait< HybridVector, CompressedVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, bool TF, typename T2 > +struct MultTrait< CompressedVector, DynamicVector > +{ + using Type = CompressedVector< MultTrait_, TF >; +}; + +template< typename T1, typename T2 > +struct MultTrait< CompressedVector, DynamicVector > +{ + using Type = CompressedMatrix< MultTrait_, true >; +}; + +template< typename T1, typename T2 > +struct MultTrait< CompressedVector, DynamicVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, bool TF, typename T2 > +struct MultTrait< DynamicVector, CompressedVector > +{ + using Type = CompressedVector< MultTrait_, TF >; +}; + +template< typename T1, typename T2 > +struct MultTrait< DynamicVector, CompressedVector > +{ + using Type = CompressedMatrix< MultTrait_, false >; +}; + +template< typename T1, typename T2 > +struct MultTrait< DynamicVector, CompressedVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, bool TF, typename T2, bool AF, bool PF > +struct MultTrait< CompressedVector, CustomVector > +{ + using Type = CompressedVector< MultTrait_, TF >; +}; + +template< typename T1, typename T2, bool AF, bool PF > +struct MultTrait< CompressedVector, CustomVector > +{ + using Type = CompressedMatrix< MultTrait_, true >; +}; + +template< typename T1, typename T2, bool AF, bool PF > +struct MultTrait< CompressedVector, CustomVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2 > +struct MultTrait< CustomVector, CompressedVector > +{ + using Type = CompressedVector< MultTrait_, TF >; +}; + +template< typename T1, bool AF, bool PF, typename T2 > +struct MultTrait< CustomVector, CompressedVector > +{ + using Type = CompressedMatrix< MultTrait_, false >; +}; + +template< typename T1, bool AF, bool PF, typename T2 > +struct MultTrait< CustomVector, CompressedVector > +{ + using Type = MultTrait_; +}; + +template< typename T1, bool TF, typename T2 > +struct MultTrait< CompressedVector, CompressedVector > +{ + using Type = CompressedVector< MultTrait_, TF >; +}; + +template< typename T1, typename T2 > +struct MultTrait< CompressedVector, CompressedVector > +{ + using Type = CompressedMatrix< MultTrait_, false >; +}; + +template< typename T1, typename T2 > +struct MultTrait< CompressedVector, CompressedVector > +{ + using Type = MultTrait_; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// CROSSTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool TF, typename T2 > +struct CrossTrait< CompressedVector, StaticVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct CrossTrait< StaticVector, CompressedVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct CrossTrait< CompressedVector, HybridVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct CrossTrait< HybridVector, CompressedVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct CrossTrait< CompressedVector, DynamicVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct CrossTrait< DynamicVector, CompressedVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct CrossTrait< CompressedVector, CompressedVector > +{ + private: + using T = MultTrait_; + + public: + using Type = StaticVector< SubTrait_, 3UL, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool TF, typename T2 > +struct DivTrait< CompressedVector, T2, EnableIf_< IsNumeric > > +{ + using Type = CompressedVector< DivTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct DivTrait< CompressedVector, StaticVector > +{ + using Type = CompressedVector< DivTrait_, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct DivTrait< StaticVector, CompressedVector > +{ + using Type = CompressedVector< DivTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2, size_t N > +struct DivTrait< CompressedVector, HybridVector > +{ + using Type = CompressedVector< DivTrait_, TF >; +}; + +template< typename T1, size_t N, bool TF, typename T2 > +struct DivTrait< HybridVector, CompressedVector > +{ + using Type = CompressedVector< DivTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct DivTrait< CompressedVector, DynamicVector > +{ + using Type = CompressedVector< DivTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct DivTrait< DynamicVector, CompressedVector > +{ + using Type = CompressedVector< DivTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2, bool AF, bool PF > +struct DivTrait< CompressedVector, CustomVector > +{ + using Type = CompressedVector< DivTrait_, TF >; +}; + +template< typename T1, bool AF, bool PF, bool TF, typename T2 > +struct DivTrait< CustomVector, CompressedVector > +{ + using Type = CompressedVector< DivTrait_, TF >; +}; + +template< typename T1, bool TF, typename T2 > +struct DivTrait< CompressedVector, CompressedVector > +{ + using Type = CompressedVector< DivTrait_, TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MATHTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool TF, typename T2 > +struct MathTrait< CompressedVector, CompressedVector > +{ + using HighType = CompressedVector< typename MathTrait::HighType, TF >; + using LowType = CompressedVector< typename MathTrait::LowType , TF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTORTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T1, bool TF > +struct SubvectorTrait< CompressedVector > +{ + using Type = CompressedVector; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 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, ElementType_ > +{ + private: + //**Enumerations******************************************************************************** + //! Compile time flag indicating whether the given matrix type is a row-major matrix. + enum : bool { rmm = IsRowMajorMatrix::value }; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef ElementType_ 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 list ) const; + + template< typename T > + inline const MatrixAccessProxy& operator=( initializer_list< initializer_list > 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::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_ 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::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::~MatrixAccessProxy() +{ + const Iterator_ 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& MatrixAccessProxy::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& + MatrixAccessProxy::operator=( initializer_list 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& + MatrixAccessProxy::operator=( initializer_list< initializer_list > 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& MatrixAccessProxy::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& MatrixAccessProxy::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& MatrixAccessProxy::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& MatrixAccessProxy::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& MatrixAccessProxy::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::RawReference MatrixAccessProxy::get() const noexcept +{ + const Iterator_ 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::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::operator RawReference() const noexcept +{ + return get(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name MatrixAccessProxy global functions */ +//@{ +template< typename MT > +inline void reset( const MatrixAccessProxy& proxy ); + +template< typename MT > +inline void clear( const MatrixAccessProxy& proxy ); + +template< typename MT > +inline bool isDefault( const MatrixAccessProxy& proxy ); + +template< typename MT > +inline bool isReal( const MatrixAccessProxy& proxy ); + +template< typename MT > +inline bool isZero( const MatrixAccessProxy& proxy ); + +template< typename MT > +inline bool isOne( const MatrixAccessProxy& proxy ); + +template< typename MT > +inline bool isnan( const MatrixAccessProxy& proxy ); + +template< typename MT > +inline void swap( const MatrixAccessProxy& a, const MatrixAccessProxy& b ) noexcept; + +template< typename MT, typename T > +inline void swap( const MatrixAccessProxy& a, T& b ) noexcept; + +template< typename T, typename MT > +inline void swap( T& a, const MatrixAccessProxy& 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& 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& 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& 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& 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& 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& 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& 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& a, const MatrixAccessProxy& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name SparseMatrix operators */ +//@{ +template< typename T1, typename T2, bool SO > +inline bool operator==( const SparseMatrix& lhs, const SparseMatrix& rhs ); + +template< typename T1, typename T2, bool SO > +inline bool operator==( const SparseMatrix& lhs, const SparseMatrix& rhs ); + +template< typename T1, typename T2, bool SO > +inline bool operator==( const SparseMatrix& lhs, const SparseMatrix& rhs ); + +template< typename T1, bool SO1, typename T2, bool SO2 > +inline bool operator!=( const SparseMatrix& lhs, const SparseMatrix& 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& lhs, const SparseMatrix& rhs ) +{ + typedef CompositeType_ CT1; + typedef CompositeType_ CT2; + typedef ConstIterator_< RemoveReference_ > LhsConstIterator; + typedef ConstIterator_< RemoveReference_ > 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; iindex() < 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& lhs, const SparseMatrix& rhs ) +{ + typedef CompositeType_ CT1; + typedef CompositeType_ CT2; + typedef ConstIterator_< RemoveReference_ > LhsConstIterator; + typedef ConstIterator_< RemoveReference_ > 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; jindex() < 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& lhs, const SparseMatrix& rhs ) +{ + const OppositeType_ 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& lhs, const SparseMatrix& rhs ) +{ + return !( lhs == rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name SparseMatrix functions */ +//@{ +template< typename MT, bool SO > +bool isnan( const SparseMatrix& sm ); + +template< typename MT, bool SO > +bool isSymmetric( const SparseMatrix& sm ); + +template< typename MT, bool SO > +bool isHermitian( const SparseMatrix& sm ); + +template< typename MT, bool SO > +bool isUniform( const SparseMatrix& sm ); + +template< typename MT, bool SO > +bool isLower( const SparseMatrix& sm ); + +template< typename MT, bool SO > +bool isUniLower( const SparseMatrix& sm ); + +template< typename MT, bool SO > +bool isStrictlyLower( const SparseMatrix& sm ); + +template< typename MT, bool SO > +bool isUpper( const SparseMatrix& sm ); + +template< typename MT, bool SO > +bool isUniUpper( const SparseMatrix& sm ); + +template< typename MT, bool SO > +bool isStrictlyUpper( const SparseMatrix& sm ); + +template< typename MT, bool SO > +bool isDiagonal( const SparseMatrix& sm ); + +template< typename MT, bool SO > +bool isIdentity( const SparseMatrix& sm ); + +template< typename MT, bool SO > +const ElementType_ min( const SparseMatrix& sm ); + +template< typename MT, bool SO > +const ElementType_ max( const SparseMatrix& 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 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& sm ) +{ + typedef CompositeType_ CT; + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + CT A( ~sm ); // Evaluation of the sparse matrix operand + + if( SO == rowMajor ) { + for( size_t i=0UL; ivalue() ) ) return true; + } + } + else { + for( size_t j=0UL; jvalue() ) ) 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 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& sm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + if( IsSymmetric::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; iindex() ); + + 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; jindex() ); + + 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 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& sm ) +{ + typedef ResultType_ RT; + typedef ElementType_ ET; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + if( IsHermitian::value ) + return true; + + if( !IsNumeric::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; iindex() ); + + 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; jindex() ); + + 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& 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_ ConstIterator; + + const size_t ibegin( ( IsStrictlyLower::value )?( 1UL ):( 0UL ) ); + const size_t iend ( ( IsStrictlyUpper::value )?( (~sm).rows()-1UL ):( (~sm).rows() ) ); + + for( size_t i=ibegin; ivalue() ) ) + 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& 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_ ConstIterator; + + const size_t jbegin( ( IsStrictlyUpper::value )?( 1UL ):( 0UL ) ); + const size_t jend ( ( IsStrictlyLower::value )?( (~sm).columns()-1UL ):( (~sm).columns() ) ); + + for( size_t j=jbegin; jvalue() ) ) + 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& 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_ ConstReference; + typedef ConstIterator_ 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& 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_ ConstReference; + typedef ConstIterator_ 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 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& sm ) +{ + if( IsUniTriangular::value ) + return false; + + if( (~sm).rows() == 0UL || (~sm).columns() == 0UL || + ( (~sm).rows() == 1UL && (~sm).columns() == 1UL ) ) + return true; + + CompositeType_ A( ~sm ); // Evaluation of the sparse matrix operand + + return isUniform_backend( A, typename IsTriangular::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 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& sm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + if( IsLower::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; ivalue() ) ) + return false; + } + } + } + else { + for( size_t j=1UL; jindex() >= 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 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& sm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + if( IsUniLower::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; iindex() != 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; jindex() >= 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 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& sm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + if( IsStrictlyLower::value ) + return true; + + if( IsUniLower::value || IsUniUpper::value || !isSquare( ~sm ) ) + return false; + + Tmp A( ~sm ); // Evaluation of the sparse matrix operand + + if( SO == rowMajor ) { + for( size_t i=0UL; ivalue() ) ) + return false; + } + } + } + else { + for( size_t j=0UL; jindex() > 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 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& sm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + if( IsUpper::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; iindex() >= i ) + break; + + if( !isDefault( element->value() ) ) + return false; + } + } + } + else { + for( size_t j=0UL; jvalue() ) ) + 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 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& sm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + if( IsUniUpper::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; iindex() >= 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; jindex() != 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 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& sm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + if( IsStrictlyUpper::value ) + return true; + + if( IsUniLower::value || IsUniUpper::value || !isSquare( ~sm ) ) + return false; + + Tmp A( ~sm ); // Evaluation of the sparse matrix operand + + if( SO == rowMajor ) { + for( size_t i=0UL; iindex() > i ) + break; + + if( !isDefault( element->value() ) ) + return false; + } + } + } + else { + for( size_t j=0UL; jvalue() ) ) + 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 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& sm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + if( IsDiagonal::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; iindex() != i && !isDefault( element->value() ) ) + return false; + } + } + else { + for( size_t j=0UL; jindex() != 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 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& sm ) +{ + typedef ResultType_ RT; + typedef ReturnType_ RN; + typedef CompositeType_ CT; + typedef If_< IsExpression, const RT, CT > Tmp; + typedef ConstIterator_< RemoveReference_ > ConstIterator; + + if( IsIdentity::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; iindex() == 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; jindex() == 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_ min( const SparseMatrix& sm ) +{ + using blaze::min; + + typedef ElementType_ ET; + typedef CompositeType_ CT; + typedef ConstIterator_< RemoveReference_ > 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; ivalue() ); + } + + 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_ max( const SparseMatrix& sm ) +{ + using blaze::max; + + typedef ElementType_ ET; + typedef CompositeType_ CT; + typedef ConstIterator_< RemoveReference_ > 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; ivalue() ); + } + + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name SparseVector operators */ +//@{ +template< typename T1, bool TF1, typename T2, bool TF2 > +inline bool operator==( const SparseVector& lhs, const SparseVector& rhs ); + +template< typename T1, bool TF1, typename T2, bool TF2 > +inline bool operator!=( const SparseVector& lhs, const SparseVector& 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& lhs, const SparseVector& rhs ) +{ + typedef CompositeType_ CT1; + typedef CompositeType_ CT2; + typedef ConstIterator_< RemoveReference_ > LhsConstIterator; + typedef ConstIterator_< RemoveReference_ > 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& lhs, const SparseVector& rhs ) +{ + return !( lhs == rhs ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name SparseVector functions */ +//@{ +template< typename VT, bool TF > +bool isnan( const SparseVector& sv ); + +template< typename VT, bool TF > +bool isUniform( const SparseVector& dv ); + +template< typename VT, bool TF > +const ElementType_ sqrLength( const SparseVector& sv ); + +template< typename VT, bool TF > +inline auto length( const SparseVector& sv ) -> decltype( sqrt( sqrLength( ~sv ) ) ); + +template< typename VT, bool TF > +const ElementType_ min( const SparseVector& sv ); + +template< typename VT, bool TF > +const ElementType_ max( const SparseVector& 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 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& sv ) +{ + typedef CompositeType_ CT; + typedef ConstIterator_< RemoveReference_ > 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 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& sv ) +{ + typedef CompositeType_ CT; + typedef ConstReference_< RemoveReference_ > ConstReference; + typedef ConstIterator_< RemoveReference_ > 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_ sqrLength( const SparseVector& sv ) +{ + typedef ElementType_ ElementType; + typedef ConstIterator_ 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: +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +//
\b Type \b LengthType
floatfloat
integral data types and doubledouble
long doublelong double
complexcomplex
+// +// \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& 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_ min( const SparseVector& sv ) +{ + using blaze::min; + + typedef ElementType_ ET; + typedef CompositeType_ CT; + typedef ConstIterator_< RemoveReference_ > 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_ max( const SparseVector& sv ) +{ + using blaze::max; + + typedef ElementType_ ET; + typedef CompositeType_ CT; + typedef ConstIterator_< RemoveReference_ > 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 +#include +#include +#include +#include +#include +#include +#include +#include + + +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, ValueIndexPair& > operator=( const Other& rhs ); + + template< typename Other > + inline DisableIf_< IsSparseElement, 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::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::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, ValueIndexPair& > + ValueIndexPair::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, ValueIndexPair& > + ValueIndexPair::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& ValueIndexPair::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& ValueIndexPair::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& ValueIndexPair::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& ValueIndexPair::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::Reference ValueIndexPair::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::ConstReference ValueIndexPair::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::IndexType ValueIndexPair::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 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, ElementType_ > +{ + public: + //**Type definitions**************************************************************************** + typedef ElementType_ 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 list ) const; + + template< typename T > + inline const VectorAccessProxy& operator=( initializer_list< initializer_list > 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::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_ 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::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::~VectorAccessProxy() +{ + const Iterator_ 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& VectorAccessProxy::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& + VectorAccessProxy::operator=( initializer_list 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& + VectorAccessProxy::operator=( initializer_list< initializer_list > 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& VectorAccessProxy::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& VectorAccessProxy::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& VectorAccessProxy::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& VectorAccessProxy::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& VectorAccessProxy::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::RawReference VectorAccessProxy::get() const noexcept +{ + const Iterator_ 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::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::operator RawReference() const noexcept +{ + return get(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL FUNCTIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name VectorAccessProxy global functions */ +//@{ +template< typename VT > +inline void reset( const VectorAccessProxy& proxy ); + +template< typename VT > +inline void clear( const VectorAccessProxy& proxy ); + +template< typename VT > +inline bool isDefault( const VectorAccessProxy& proxy ); + +template< typename VT > +inline bool isReal( const VectorAccessProxy& proxy ); + +template< typename VT > +inline bool isZero( const VectorAccessProxy& proxy ); + +template< typename VT > +inline bool isOne( const VectorAccessProxy& proxy ); + +template< typename VT > +inline bool isnan( const VectorAccessProxy& proxy ); + +template< typename VT > +inline void swap( const VectorAccessProxy& a, const VectorAccessProxy& b ) noexcept; + +template< typename VT, typename T > +inline void swap( const VectorAccessProxy& a, T& b ) noexcept; + +template< typename T, typename VT > +inline void swap( T& a, const VectorAccessProxy& 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& 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& 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& 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& 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& 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& 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& 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& a, const VectorAccessProxy& 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& 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& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + , If_< IsMatrix + , If_< IsDenseMatrix + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , If_< IsRowMajorMatrix + , DMatDMatAddExprTrait + , DMatTDMatAddExprTrait > + , If_< IsRowMajorMatrix + , TDMatDMatAddExprTrait + , TDMatTDMatAddExprTrait > > + , If_< IsRowMajorMatrix + , If_< IsRowMajorMatrix + , DMatSMatAddExprTrait + , DMatTSMatAddExprTrait > + , If_< IsRowMajorMatrix + , TDMatSMatAddExprTrait + , TDMatTSMatAddExprTrait > > > + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , If_< IsRowMajorMatrix + , SMatDMatAddExprTrait + , SMatTDMatAddExprTrait > + , If_< IsRowMajorMatrix + , TSMatDMatAddExprTrait + , TSMatTDMatAddExprTrait > > + , If_< IsRowMajorMatrix + , If_< IsRowMajorMatrix + , SMatSMatAddExprTrait + , SMatTSMatAddExprTrait > + , If_< IsRowMajorMatrix + , TSMatSMatAddExprTrait + , TSMatTSMatAddExprTrait > > > > + , Failure > + , If_< IsVector + , If_< IsVector + , If_< IsDenseVector + , If_< IsDenseVector + , If_< IsRowVector + , If_< IsRowVector + , TDVecTDVecAddExprTrait + , Failure > + , If_< IsRowVector + , Failure + , DVecDVecAddExprTrait > > + , If_< IsRowVector + , If_< IsRowVector + , TDVecTSVecAddExprTrait + , Failure > + , If_< IsRowVector + , Failure + , DVecSVecAddExprTrait > > > + , If_< IsDenseVector + , If_< IsRowVector + , If_< IsRowVector + , TSVecTDVecAddExprTrait + , Failure > + , If_< IsRowVector + , Failure + , SVecDVecAddExprTrait > > + , If_< IsRowVector + , If_< IsRowVector + , TSVecTSVecAddExprTrait + , Failure > + , If_< IsRowVector + , Failure + , SVecSVecAddExprTrait > > > > + , Failure > + , If_< IsNumeric + , If_< IsNumeric + , AddTrait + , Failure > + , Failure > > >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , AddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = AddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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: +// +//
    +//
  • std::complex
  • +//
  • blaze::StaticVector
  • +//
  • blaze::HybridVector
  • +//
  • blaze::DynamicVector
  • +//
  • blaze::CustomVector
  • +//
  • blaze::CompressedVector
  • +//
  • blaze::StaticMatrix
  • +//
  • blaze::HybridMatrix
  • +//
  • blaze::DynamicMatrix
  • +//
  • blaze::CustomMatrix
  • +//
  • blaze::CompressedMatrix
  • +//
  • blaze::SymmetricMatrix
  • +//
  • blaze::HermitianMatrix
  • +//
  • blaze::LowerMatrix
  • +//
  • blaze::UniLowerMatrix
  • +//
  • blaze::StrictlyLowerMatrix
  • +//
  • blaze::UpperMatrix
  • +//
  • blaze::UniUpperMatrix
  • +//
  • blaze::StrictlyUpperMatrix
  • +//
  • blaze::DiagonalMatrix
  • +//
+// +// +// \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, DynamicVector > + { + typedef DynamicVector< typename AddTrait::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::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_; + using Type2 = Decay_; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + struct AddType { using Type = decltype( std::declval() + std::declval() ); }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , AddTrait + , 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, T2, EnableIf_< IsBuiltin > > +{ + public: + //********************************************************************************************** + using Type = CommonType_< complex , 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, EnableIf_< IsBuiltin > > +{ + public: + //********************************************************************************************** + using Type = CommonType_< T1, complex >; + //********************************************************************************************** +}; +/*! \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, complex > +{ + public: + //********************************************************************************************** + using Type = CommonType_< complex, complex >; + //********************************************************************************************** +}; +/*! \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::Type; + using Type2 = AddTrait_; + \endcode +*/ +template< typename T1, typename T2 > +using AddTrait_ = typename AddTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , DMatCTransExprTrait + , TDMatCTransExprTrait > + , If_< IsRowMajorMatrix + , SMatCTransExprTrait + , TSMatCTransExprTrait > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsRowVector + , TDVecCTransExprTrait + , DVecCTransExprTrait > + , If_< IsRowVector + , TSVecCTransExprTrait + , SVecCTransExprTrait > > + , Failure > >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , CTransExprTrait< Decay_ > + , 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::Type; + using Type2 = CTransExprTrait_; + \endcode +*/ +template< typename T > // Type of the conjugate transpose operand +using CTransExprTrait_ = typename CTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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::value,IsDenseMatrix::value,IsSymmetric::value>; + }; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Tmp = RemoveReference_; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsComputation, IsTransExpr > + , If_< Or< IsConst, IsVolatile > + , ColumnExprTrait< RemoveCV_ > + , Failure > + , If_< IsMatrix + , Result + , 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::Type; + using Type2 = ColumnExprTrait_; + \endcode +*/ +template< typename MT > // Type of the matrix operand +using ColumnExprTrait_ = typename ColumnExprTrait::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 +#include +#include +#include +#include +#include +#include + + +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: +// +//
    +//
  • blaze::StaticMatrix
  • +//
  • blaze::HybridMatrix
  • +//
  • blaze::DynamicMatrix
  • +//
  • blaze::CustomMatrix
  • +//
  • blaze::CompressedMatrix
  • +//
  • blaze::Submatrix
  • +//
+// +// +// \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 > + { + typedef DynamicVector 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 MatrixType1; + typedef typename ColumnTrait::Type ColumnType1; + + // Definition of the column type of the row-major static matrix + typedef blaze::StaticMatrix MatrixType2; + typedef typename ColumnTrait::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, IsVolatile, IsReference > + , ColumnTrait< Decay_ > + , 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::Type; + using Type2 = ColumnTrait_; + \endcode +*/ +template< typename MT > // Type of the matrix +using ColumnTrait_ = typename ColumnTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + , If_< IsVector + , If_< IsColumnVector + , If_< IsColumnVector + , If_< IsDenseVector + , If_< IsDenseVector + , DVecDVecCrossExprTrait + , DVecSVecCrossExprTrait > + , If_< IsDenseVector + , SVecDVecCrossExprTrait + , SVecSVecCrossExprTrait > > + , Failure > + , If_< IsRowVector + , If_< IsDenseVector + , If_< IsDenseVector + , TDVecTDVecCrossExprTrait + , TDVecTSVecCrossExprTrait > + , If_< IsDenseVector + , TSVecTDVecCrossExprTrait + , TSVecTSVecCrossExprTrait > > + , Failure > > + , Failure > + , Failure >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , CrossExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = CrossExprTrait_; + \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::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 +#include +#include + + +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: +// +//
    +//
  • blaze::StaticVector
  • +//
  • blaze::DynamicVector
  • +//
  • blaze::CompressedVector
  • +//
+// +// +// \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, StaticVector > + { + typedef StaticVector< typename SubTrait< typename MultTrait::Type + , typename MultTrait::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::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::Type; + using Type2 = CrossTrait_; + \endcode +*/ +template< typename T1, typename T2 > +using CrossTrait_ = typename CrossTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix > + , DMatTransExprTrait< DMatForEachExprTrait_ > + , Failure > Tmp; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename If_< Or< IsConst, IsVolatile, IsReference > + , DMatCTransExprTrait< Decay_ > + , 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::Type; + using Type2 = DMatCTransExprTrait_; + \endcode +*/ +template< typename MT > // Type of the dense matrix +using DMatCTransExprTrait_ = typename DMatCTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatDMatAddExpr + , INVALID_TYPE > Tmp; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatDMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DMatDMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatDMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatDMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DMatDMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , DMatDMatSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatDMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DMatDMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsDenseVector, IsColumnVector > + , DMatDVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatDVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DMatDVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix > + , DMatEvalExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , DMatEvalExprTrait< Decay_ > + , 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::Type; + using Type2 = DMatEvalExprTrait_; + \endcode +*/ +template< typename MT > // Type of the dense matrix +using DMatEvalExprTrait_ = typename DMatEvalExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix > + , DMatForEachExpr + , INVALID_TYPE > Tmp; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename If_< Or< IsConst, IsVolatile, IsReference > + , DMatForEachExprTrait< Decay_, 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::Type; + using Type2 = DMatForEachExprTrait_; + \endcode +*/ +template< typename MT // Type of the dense matrix + , typename OP > // Type of the custom operation +using DMatForEachExprTrait_ = typename DMatForEachExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix > + , DMatInvExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , DMatInvExprTrait< Decay_ > + , 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::Type; + using Type2 = DMatInvExprTrait_; + \endcode +*/ +template< typename MT > // Type of the dense matrix +using DMatInvExprTrait_ = typename DMatInvExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , DMatSMatAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatSMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DMatSMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , DMatSMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatSMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DMatSMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , DMatSMatSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatSMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DMatSMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsRowMajorMatrix + , IsSparseVector, IsColumnVector > + , If_< IsSymmetric + , TDMatSVecMultExpr< DMatTransExprTrait_, VT > + , DMatSVecMultExpr > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatSVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DMatSVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , DivTrait_< UnderlyingBuiltin_, ST > + , DivTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< IsInvertible + , DMatScalarMultExpr + , DMatScalarDivExpr >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the DMatScalarDivExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename MT + , typename ST > +struct DMatScalarDivExprTraitHelper +{ + 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, IsRowMajorMatrix, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatScalarDivExprTrait< Decay_, Decay_ > + , DMatScalarDivExprTraitHelper >::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::Type; + using Type2 = DMatScalarDivExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , MultTrait_< UnderlyingBuiltin_, ST > + , MultTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = DMatScalarMultExpr; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the DMatScalarMultExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename MT + , typename ST > +struct DMatScalarMultExprTraitHelper +{ + 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, IsRowMajorMatrix, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatScalarMultExprTrait< Decay_, Decay_ > + , DMatScalarMultExprTraitHelper >::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::Type; + using Type2 = DMatScalarMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix > + , DMatSerialExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , DMatSerialExprTrait< Decay_ > + , 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::Type; + using Type2 = DMatSerialExprTrait_; + \endcode +*/ +template< typename MT > // Type of the dense matrix +using DMatSerialExprTrait_ = typename DMatSerialExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , If_< IsSymmetric + , DMatDMatAddExpr< MT1, TDMatTransExprTrait_, false > + , If_< IsSymmetric + , DMatDMatAddExpr< DMatTransExprTrait_, MT2, true > + , DMatTDMatAddExpr > > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatTDMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DMatTDMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , DMatTDMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatTDMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DMatTDMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , If_< IsSymmetric + , DMatDMatSubExpr< MT1, TDMatTransExprTrait_, false > + , If_< IsSymmetric + , DMatDMatSubExpr< DMatTransExprTrait_, MT2, true > + , DMatTDMatSubExpr > > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatTDMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DMatTDMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , DMatTSMatAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatTSMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DMatTSMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , DMatTSMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatTSMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DMatTSMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , DMatTSMatSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DMatTSMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DMatTSMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix > + , DMatTransExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , DMatTransExprTrait< Decay_ > + , 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::Type; + using Type2 = DMatTransExprTrait_; + \endcode +*/ +template< typename MT > // Type of the dense matrix +using DMatTransExprTrait_ = typename DMatTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector > + , DVecTransExprTrait< DVecForEachExprTrait_ > + , Failure >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , DVecCTransExprTrait< Decay_ > + , 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::Type; + using Type2 = DVecCTransExprTrait_; + \endcode +*/ +template< typename VT > // Type of the dense vector +using DVecCTransExprTrait_ = typename DVecCTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsDenseVector, IsColumnVector > + , DVecDVecAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DVecDVecAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DVecDVecAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsDenseVector, IsColumnVector > + , DVecDVecCrossExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DVecDVecCrossExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DVecDVecCrossExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsDenseVector, IsColumnVector > + , DVecDVecDivExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DVecDVecDivExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DVecDVecDivExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsDenseVector, IsColumnVector > + , DVecDVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DVecDVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DVecDVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsDenseVector, IsColumnVector > + , DVecDVecSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DVecDVecSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DVecDVecSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector > + , DVecEvalExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , DVecEvalExprTrait< Decay_ > + , 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::Type; + using Type2 = DVecEvalExprTrait_; + \endcode +*/ +template< typename VT > // Type of the dense vector +using DVecEvalExprTrait_ = typename DVecEvalExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector > + , DVecForEachExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , DVecForEachExprTrait< Decay_, 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::Type; + using Type2 = DVecForEachExprTrait_; + \endcode +*/ +template< typename VT // Type of the dense vector + , typename OP > // Type of the custom operation +using DVecForEachExprTrait_ = typename DVecForEachExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsColumnVector + , IsSparseVector, IsColumnVector > + , DVecSVecAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DVecSVecAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DVecSVecAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsColumnVector + , IsSparseVector, IsColumnVector > + , DVecSVecCrossExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DVecSVecCrossExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DVecSVecCrossExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsColumnVector + , IsSparseVector, IsColumnVector > + , DVecSVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DVecSVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DVecSVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsColumnVector + , IsSparseVector, IsColumnVector > + , DVecSVecSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DVecSVecSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DVecSVecSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , DivTrait_< UnderlyingBuiltin_, ST > + , DivTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< IsInvertible + , DVecScalarMultExpr + , DVecScalarDivExpr >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the DVecScalarDivExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename VT + , typename ST > +struct DVecScalarDivExprTraitHelper +{ + 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, IsColumnVector, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DVecScalarDivExprTrait< Decay_, Decay_ > + , DVecScalarDivExprTraitHelper >::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::Type; + using Type2 = DVecScalarDivExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , MultTrait_< UnderlyingBuiltin_, ST > + , MultTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = DVecScalarMultExpr; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the DVecScalarMultExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename VT + , typename ST > +struct DVecScalarMultExprTraitHelper +{ + 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, IsColumnVector, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DVecScalarMultExprTrait< Decay_, Decay_ > + , DVecScalarMultExprTraitHelper >::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::Type; + using Type2 = DVecScalarMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector > + , DVecSerialExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , DVecSerialExprTrait< Decay_ > + , 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::Type; + using Type2 = DVecSerialExprTrait_; + \endcode +*/ +template< typename VT > // Type of the dense vector +using DVecSerialExprTrait_ = typename DVecSerialExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsDenseVector, IsRowVector > + , DVecTDVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DVecTDVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DVecTDVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsColumnVector + , IsSparseVector, IsRowVector > + , DVecTSVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DVecTSVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DVecTSVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector > + , DVecTransExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , DVecTransExprTrait< Decay_ > + , 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::Type; + using Type2 = DVecTransExprTrait_; + \endcode +*/ +template< typename VT > // Type of the dense vector +using DVecTransExprTrait_ = typename DVecTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsMatrix > + , AddReference_ + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , DerestrictTrait< Decay_ > + , 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::Type; + using Type2 = DerestrictTrait_; + \endcode +*/ +template< typename T > +using DerestrictTrait_ = typename DerestrictTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , If_< IsNumeric + , DMatScalarDivExprTrait + , Failure > + , If_< IsNumeric + , TDMatScalarDivExprTrait + , Failure > > + , If_< IsRowMajorMatrix + , If_< IsNumeric + , SMatScalarDivExprTrait + , Failure > + , If_< IsNumeric + , TSMatScalarDivExprTrait + , Failure > > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsRowVector + , If_< IsVector + , If_< IsDenseVector + , If_< IsRowVector + , TDVecTDVecDivExprTrait + , Failure > + , Failure > + , If_< IsNumeric + , TDVecScalarDivExprTrait + , Failure > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsColumnVector + , DVecDVecDivExprTrait + , Failure > + , Failure > + , If_< IsNumeric + , DVecScalarDivExprTrait + , Failure > > > + , If_< IsRowVector + , If_< IsVector + , If_< IsDenseVector + , If_< IsRowVector + , TSVecTDVecDivExprTrait + , Failure > + , Failure > + , If_< IsNumeric + , TSVecScalarDivExprTrait + , Failure > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsColumnVector + , SVecDVecDivExprTrait + , Failure > + , Failure > + , If_< IsNumeric + , SVecScalarDivExprTrait + , Failure > > > > + , If_< IsNumeric + , If_< IsNumeric + , DivTrait + , Failure > + , Failure > > >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DivExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = DivExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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: +// +//
    +//
  • std::complex
  • +//
  • blaze::StaticVector
  • +//
  • blaze::HybridVector
  • +//
  • blaze::DynamicVector
  • +//
  • blaze::CustomVector
  • +//
  • blaze::CompressedVector
  • +//
  • blaze::StaticMatrix
  • +//
  • blaze::HybridMatrix
  • +//
  • blaze::DynamicMatrix
  • +//
  • blaze::CustomMatrix
  • +//
  • blaze::CompressedMatrix
  • +//
  • blaze::SymmetricMatrix
  • +//
  • blaze::HermitianMatrix
  • +//
  • blaze::LowerMatrix
  • +//
  • blaze::UniLowerMatrix
  • +//
  • blaze::StrictlyLowerMatrix
  • +//
  • blaze::UpperMatrix
  • +//
  • blaze::UniUpperMatrix
  • +//
  • blaze::StrictlyUpperMatrix
  • +//
  • blaze::DiagonalMatrix
  • +//
+// +// +// \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, double > + { + typedef DynamicVector< typename DivTrait::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::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_; + using Type2 = Decay_; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + struct DivType { using Type = decltype( std::declval() / std::declval() ); }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , DivTrait + , 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, T2, EnableIf_< IsBuiltin > > +{ + public: + //********************************************************************************************** + using Type = CommonType_< complex , 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, EnableIf_< IsBuiltin > > +{ + public: + //********************************************************************************************** + using Type = CommonType_< T1, complex >; + //********************************************************************************************** +}; +/*! \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, complex > +{ + public: + //********************************************************************************************** + using Type = CommonType_< complex, complex >; + //********************************************************************************************** +}; +/*! \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::Type; + using Type2 = DivTrait_; + \endcode +*/ +template< typename T1, typename T2 > +using DivTrait_ = typename DivTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , DMatEvalExprTrait + , TDMatEvalExprTrait > + , If_< IsRowMajorMatrix + , SMatEvalExprTrait + , TSMatEvalExprTrait > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsRowVector + , TDVecEvalExprTrait + , DVecEvalExprTrait > + , If_< IsRowVector + , TSVecEvalExprTrait + , SVecEvalExprTrait > > + , Failure > >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , EvalExprTrait< Decay_ > + , 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::Type; + using Type2 = EvalExprTrait_; + \endcode +*/ +template< typename T > // Type of the evaluation operand +using EvalExprTrait_ = typename EvalExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , DMatForEachExprTrait + , TDMatForEachExprTrait > + , If_< IsRowMajorMatrix + , SMatForEachExprTrait + , TSMatForEachExprTrait > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsRowVector + , TDVecForEachExprTrait + , DVecForEachExprTrait > + , If_< IsRowVector + , TSVecForEachExprTrait + , SVecForEachExprTrait > > + , Failure > >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , ForEachExprTrait< Decay_, 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::Type; + using Type2 = ForEachExprTrait_; + \endcode +*/ +template< typename T // Type of the forEach operand + , typename OP > // Type of the custom operation +using ForEachExprTrait_ = typename ForEachExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsMatrix >, U > test( U&& ); + + template< typename U > + static EnableIf_< Or< IsVector, IsMatrix >, ResultType_ > test( U&& ); + + using RT = RemoveAdaptor_< ResultType_ >; + using RN = ReturnType_; + + using OT = decltype( std::declval()( std::declval() ) ); + using ET = decltype( test( std::declval() ) ); + + using Type = typename RT::template Rebind::Other; + }; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + struct Failure { + using Type = INVALID_TYPE; + }; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Tmp = If_< Or< IsMatrix, IsVector > + , MatrixOrVector + , Failure >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , ForEachTrait< Decay_, 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::Type; + using Type2 = ForEachTrait_; + \endcode +*/ +template< typename T // Type of the operand + , typename OP > // Type of the custom operation +using ForEachTrait_ = typename ForEachTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >::Type; + using Type = typename T::template Rebind::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, IsVector > + , MatrixOrVector + , If_< IsBuiltin + , Builtin + , If_< IsComplex + , Complex + , Failure > > >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , ImagTrait< Decay_ > + , 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::Type; + using Type2 = ImagTrait_; + \endcode +*/ +template< typename T > // Type of the operand +using ImagTrait_ = typename ImagTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsBLASCompatible< UnderlyingElement_ > > + , If_< IsRowMajorMatrix + , DMatInvExprTrait + , TDMatInvExprTrait > + , If_< Or< IsFloatingPoint + , And< IsComplex, IsFloatingPoint< UnderlyingElement_ > > > + , Scalar + , Failure > >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , InvExprTrait< Decay_ > + , 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::Type; + using Type2 = InvExprTrait_; + \endcode +*/ +template< typename T > // Type of the inversion operand +using InvExprTrait_ = typename InvExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include + + +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: +// +//
    +//
  • Integral types
  • +//
      +//
    • unsigned char, signed char, char, wchar_t
    • +//
    • unsigned short, short
    • +//
    • unsigned int, int
    • +//
    • unsigned long, long
    • +//
    • std::size_t, std::ptrdiff_t (for certain 64-bit compilers)
    • +//
    +//
  • Floating point types
  • +//
      +//
    • float
    • +//
    • double
    • +//
    • long double
    • +//
    +//
+// +// Additionally, the Blaze library provides specializations for the following user-defined +// arithmetic types, wherever a more/less significant data type can be selected: +// +//
    +//
  • std::complex
  • +//
  • blaze::StaticVector
  • +//
  • blaze::HybridVector
  • +//
  • blaze::DynamicVector
  • +//
  • blaze::CompressedVector
  • +//
  • blaze::StaticMatrix
  • +//
  • blaze::HybridMatrix
  • +//
  • blaze::DynamicMatrix
  • +//
  • blaze::CompressedMatrix
  • +//
  • blaze::SymmetricMatrix
  • +//
  • blaze::LowerMatrix
  • +//
  • blaze::UniLowerMatrix
  • +//
  • blaze::StrictlyLowerMatrix
  • +//
  • blaze::UpperMatrix
  • +//
  • blaze::UniUpperMatrix
  • +//
  • blaze::StrictlyUpperMatrix
  • +//
  • blaze::DiagonalMatrix
  • +//
+// +// +// \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, DynamicVector > + { + typedef DynamicVector< typename MathTrait::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_, Decay_ >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using HighType = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , Helper + , Failure >::HighType; + + using LowType = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , 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 +{ + //********************************************************************************************** + using HighType = Decay_; + 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 > \ + { \ + using HighType = complex; \ + using LowType = T1; \ + }; \ + template< typename T2 > \ + struct MathTrait< complex, T1 > \ + { \ + using HighType = complex; \ + 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, complex > +{ + using HighType = complex::HighType>; + using LowType = complex::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , If_< IsMatrix + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , DMatDMatMultExprTrait + , DMatTDMatMultExprTrait > + , If_< IsRowMajorMatrix + , DMatSMatMultExprTrait + , DMatTSMatMultExprTrait > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsColumnVector + , DMatDVecMultExprTrait + , Failure > + , If_< IsColumnVector + , DMatSVecMultExprTrait + , Failure > > + , If_< IsNumeric + , DMatScalarMultExprTrait + , Failure > > > + , If_< IsMatrix + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , TDMatDMatMultExprTrait + , TDMatTDMatMultExprTrait > + , If_< IsRowMajorMatrix + , TDMatSMatMultExprTrait + , TDMatTSMatMultExprTrait > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsColumnVector + , TDMatDVecMultExprTrait + , Failure > + , If_< IsColumnVector + , TDMatSVecMultExprTrait + , Failure > > + , If_< IsNumeric + , TDMatScalarMultExprTrait + , Failure > > > > + , If_< IsRowMajorMatrix + , If_< IsMatrix + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , SMatDMatMultExprTrait + , SMatTDMatMultExprTrait > + , If_< IsRowMajorMatrix + , SMatSMatMultExprTrait + , SMatTSMatMultExprTrait > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsColumnVector + , SMatDVecMultExprTrait + , Failure > + , If_< IsColumnVector + , SMatSVecMultExprTrait + , Failure > > + , If_< IsNumeric + , SMatScalarMultExprTrait + , Failure > > > + , If_< IsMatrix + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , TSMatDMatMultExprTrait + , TSMatTDMatMultExprTrait > + , If_< IsRowMajorMatrix + , TSMatSMatMultExprTrait + , TSMatTSMatMultExprTrait > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsColumnVector + , TSMatDVecMultExprTrait + , Failure > + , If_< IsColumnVector + , TSMatSVecMultExprTrait + , Failure > > + , If_< IsNumeric + , TSMatScalarMultExprTrait + , Failure > > > > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsRowVector + , If_< IsMatrix + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , TDVecDMatMultExprTrait + , TDVecTDMatMultExprTrait > + , If_< IsRowMajorMatrix + , TDVecSMatMultExprTrait + , TDVecTSMatMultExprTrait > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsRowVector + , TDVecTDVecMultExprTrait + , TDVecDVecMultExprTrait > + , If_< IsRowVector + , TDVecTSVecMultExprTrait + , TDVecSVecMultExprTrait > > + , If_< IsNumeric + , TDVecScalarMultExprTrait + , Failure > > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsRowVector + , DVecTDVecMultExprTrait + , DVecDVecMultExprTrait > + , If_< IsRowVector + , DVecTSVecMultExprTrait + , DVecSVecMultExprTrait > > + , If_< IsNumeric + , DVecScalarMultExprTrait + , Failure > > > + , If_< IsRowVector + , If_< IsMatrix + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , TSVecDMatMultExprTrait + , TSVecTDMatMultExprTrait > + , If_< IsRowMajorMatrix + , TSVecSMatMultExprTrait + , TSVecTSMatMultExprTrait > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsRowVector + , TSVecTDVecMultExprTrait + , TSVecDVecMultExprTrait > + , If_< IsRowVector + , TSVecTSVecMultExprTrait + , TSVecSVecMultExprTrait > > + , If_< IsNumeric + , TSVecScalarMultExprTrait + , Failure > > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsRowVector + , SVecTDVecMultExprTrait + , SVecDVecMultExprTrait > + , If_< IsRowVector + , SVecTSVecMultExprTrait + , SVecSVecMultExprTrait > > + , If_< IsNumeric + , SVecScalarMultExprTrait + , Failure > > > > + , If_< IsNumeric + , If_< IsMatrix + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , DMatScalarMultExprTrait + , TDMatScalarMultExprTrait > + , If_< IsRowMajorMatrix + , SMatScalarMultExprTrait + , TSMatScalarMultExprTrait > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsRowVector + , TDVecScalarMultExprTrait + , DVecScalarMultExprTrait > + , If_< IsRowVector + , TSVecScalarMultExprTrait + , SVecScalarMultExprTrait > > + , If_< IsNumeric + , MultTrait + , Failure > > > + , Failure > > >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , MultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = MultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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: +// +//
    +//
  • std::complex
  • +//
  • blaze::StaticVector
  • +//
  • blaze::HybridVector
  • +//
  • blaze::DynamicVector
  • +//
  • blaze::CustomVector
  • +//
  • blaze::CompressedVector
  • +//
  • blaze::StaticMatrix
  • +//
  • blaze::HybridMatrix
  • +//
  • blaze::DynamicMatrix
  • +//
  • blaze::CustomMatrix
  • +//
  • blaze::CompressedMatrix
  • +//
  • blaze::SymmetricMatrix
  • +//
  • blaze::HermitianMatrix
  • +//
  • blaze::LowerMatrix
  • +//
  • blaze::UniLowerMatrix
  • +//
  • blaze::StrictlyLowerMatrix
  • +//
  • blaze::UpperMatrix
  • +//
  • blaze::UniUpperMatrix
  • +//
  • blaze::StrictlyUpperMatrix
  • +//
  • blaze::DiagonalMatrix
  • +//
+// +// +// \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, DynamicVector > + { + typedef DynamicVector< typename MultTrait::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::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_; + using Type2 = Decay_; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + struct MultType { using Type = decltype( std::declval() * std::declval() ); }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , MultTrait + , 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, T2, EnableIf_< IsBuiltin > > +{ + public: + //********************************************************************************************** + using Type = CommonType_< complex , 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, EnableIf_< IsBuiltin > > +{ + public: + //********************************************************************************************** + using Type = CommonType_< T1, complex >; + //********************************************************************************************** +}; +/*! \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, complex > +{ + public: + //********************************************************************************************** + using Type = CommonType_< complex, complex >; + //********************************************************************************************** +}; +/*! \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::Type; + using Type2 = MultTrait_; + \endcode +*/ +template< typename T1, typename T2 > +using MultTrait_ = typename MultTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >::Type; + using Type = typename T::template Rebind::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, IsVector > + , MatrixOrVector + , If_< IsBuiltin + , Builtin + , If_< IsComplex + , Complex + , Failure > > >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , RealTrait< Decay_ > + , 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::Type; + using Type2 = RealTrait_; + \endcode +*/ +template< typename T > // Type of the operand +using RealTrait_ = typename RealTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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::value,IsDenseMatrix::value,IsSymmetric::value>; + }; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Tmp = RemoveReference_; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsComputation, IsTransExpr > + , If_< Or< IsConst, IsVolatile > + , RowExprTrait< RemoveCV_ > + , Failure > + , If_< IsMatrix + , Result + , 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::Type; + using Type2 = RowExprTrait_; + \endcode +*/ +template< typename MT > // Type of the matrix operand +using RowExprTrait_ = typename RowExprTrait::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 +#include +#include +#include +#include +#include +#include + + +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: +// +//
    +//
  • blaze::StaticMatrix
  • +//
  • blaze::HybridMatrix
  • +//
  • blaze::DynamicMatrix
  • +//
  • blaze::CustomMatrix
  • +//
  • blaze::CompressedMatrix
  • +//
  • blaze::Submatrix
  • +//
+// +// +// \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 > + { + typedef DynamicVector 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 MatrixType1; + typedef typename RowTrait::Type RowType1; + + // Definition of the row type of the column-major static matrix + typedef blaze::StaticMatrix MatrixType2; + typedef typename RowTrait::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, IsVolatile, IsReference > + , RowTrait< Decay_ > + , 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::Type; + using Type2 = RowTrait_; + \endcode +*/ +template< typename MT > // Type of the matrix +using RowTrait_ = typename RowTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix > + , SMatTransExprTrait< SMatForEachExprTrait_ > + , Failure >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , SMatCTransExprTrait< Decay_ > + , 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::Type; + using Type2 = SMatCTransExprTrait_; + \endcode +*/ +template< typename MT > // Type of the sparse matrix +using SMatCTransExprTrait_ = typename SMatCTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsDenseMatrix , IsRowMajorMatrix > + , DMatSMatAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatDMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SMatDMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsDenseMatrix , IsRowMajorMatrix > + , SMatDMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatDMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SMatDMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsDenseMatrix , IsRowMajorMatrix > + , SMatDMatSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatDMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SMatDMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsDenseVector , IsColumnVector > + , SMatDVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatDVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SMatDVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix > + , SMatEvalExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , SMatEvalExprTrait< Decay_ > + , 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::Type; + using Type2 = SMatEvalExprTrait_; + \endcode +*/ +template< typename MT > // Type of the sparse matrix +using SMatEvalExprTrait_ = typename SMatEvalExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix > + , SMatForEachExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , SMatForEachExprTrait< Decay_, 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::Type; + using Type2 = SMatForEachExprTrait_; + \endcode +*/ +template< typename MT // Type of the sparse matrix + , typename OP > // Type of the custom operation +using SMatForEachExprTrait_ = typename SMatForEachExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , SMatSMatAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatSMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SMatSMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , SMatSMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatSMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SMatSMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , SMatSMatSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatSMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SMatSMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsSparseVector, IsColumnVector > + , If_< IsSymmetric + , TSMatSVecMultExpr< SMatTransExprTrait_, VT > + , SMatSVecMultExpr > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatSVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SMatSVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , DivTrait_< UnderlyingBuiltin_, ST > + , DivTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< IsInvertible + , SMatScalarMultExpr + , SMatScalarDivExpr >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the SMatScalarDivExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename MT + , typename ST > +struct SMatScalarDivExprTraitHelper +{ + 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, IsRowMajorMatrix, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatScalarDivExprTrait< Decay_, Decay_ > + , SMatScalarDivExprTraitHelper >::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::Type; + using Type2 = SMatScalarDivExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , MultTrait_< UnderlyingBuiltin_, ST > + , MultTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = SMatScalarMultExpr; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the SMatScalarMultExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename MT + , typename ST > +struct SMatScalarMultExprTraitHelper +{ + 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, IsRowMajorMatrix, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatScalarMultExprTrait< Decay_, Decay_ > + , SMatScalarMultExprTraitHelper >::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::Type; + using Type2 = SMatScalarMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix > + , SMatSerialExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , SMatSerialExprTrait< Decay_ > + , 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::Type; + using Type2 = SMatSerialExprTrait_; + \endcode +*/ +template< typename MT > // Type of the sparse matrix +using SMatSerialExprTrait_ = typename SMatSerialExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsDenseMatrix , IsColumnMajorMatrix > + , TDMatSMatAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatTDMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SMatTDMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsDenseMatrix , IsColumnMajorMatrix > + , SMatTDMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatTDMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SMatTDMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsDenseMatrix , IsColumnMajorMatrix > + , SMatTDMatSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatTDMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SMatTDMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , SMatTSMatAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatTSMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SMatTSMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , SMatTSMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatTSMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SMatTSMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , SMatTSMatSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SMatTSMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SMatTSMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowMajorMatrix > + , SMatTransExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , SMatTransExprTrait< Decay_ > + , 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::Type; + using Type2 = SMatTransExprTrait_; + \endcode +*/ +template< typename MT > // Type of the sparse matrix +using SMatTransExprTrait_ = typename SMatTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector > + , SVecTransExprTrait< SVecForEachExprTrait_ > + , Failure >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , SVecCTransExprTrait< Decay_ > + , 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::Type; + using Type2 = SVecCTransExprTrait_; + \endcode +*/ +template< typename VT > // Type of the sparse vector +using SVecCTransExprTrait_ = typename SVecCTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsDenseVector , IsColumnVector > + , DVecSVecAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SVecDVecAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SVecDVecAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsDenseVector , IsColumnVector > + , SVecDVecCrossExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SVecDVecCrossExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SVecDVecCrossExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsDenseVector , IsColumnVector > + , SVecDVecDivExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SVecDVecDivExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SVecDVecDivExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsDenseVector , IsColumnVector > + , SVecDVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SVecDVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SVecDVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsDenseVector , IsColumnVector > + , SVecDVecSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SVecDVecSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SVecDVecSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector > + , SVecEvalExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , SVecEvalExprTrait< Decay_ > + , 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::Type; + using Type2 = SVecEvalExprTrait_; + \endcode +*/ +template< typename VT > // Type of the sparse vector +using SVecEvalExprTrait_ = typename SVecEvalExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector > + , SVecForEachExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , SVecForEachExprTrait< Decay_, 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::Type; + using Type2 = SVecForEachExprTrait_; + \endcode +*/ +template< typename VT // Type of the sparse vector + , typename OP > // Type of the custom operation +using SVecForEachExprTrait_ = typename SVecForEachExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsSparseVector, IsColumnVector > + , SVecSVecAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SVecSVecAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SVecSVecAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsSparseVector, IsColumnVector > + , SVecSVecCrossExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SVecSVecCrossExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SVecSVecCrossExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsSparseVector, IsColumnVector > + , SVecSVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SVecSVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SVecSVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsSparseVector, IsColumnVector > + , SVecSVecSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SVecSVecSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SVecSVecSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , DivTrait_< UnderlyingBuiltin_, ST > + , DivTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< IsInvertible + , SVecScalarMultExpr + , SVecScalarDivExpr >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the SVecScalarDivExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename VT + , typename ST > +struct SVecScalarDivExprTraitHelper +{ + 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, IsColumnVector, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SVecScalarDivExprTrait< Decay_, Decay_ > + , SVecScalarDivExprTraitHelper >::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::Type; + using Type2 = SVecScalarDivExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , MultTrait_< UnderlyingBuiltin_, ST > + , MultTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = SVecScalarMultExpr; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the SVecScalarMultExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename VT + , typename ST > +struct SVecScalarMultExprTraitHelper +{ + 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, IsColumnVector, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SVecScalarMultExprTrait< Decay_, Decay_ > + , SVecScalarMultExprTraitHelper >::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::Type; + using Type2 = SVecScalarMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector > + , SVecSerialExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , SVecSerialExprTrait< Decay_ > + , 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::Type; + using Type2 = SVecSerialExprTrait_; + \endcode +*/ +template< typename VT > // Type of the sparse vector +using SVecSerialExprTrait_ = typename SVecSerialExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsDenseVector , IsRowVector > + , SVecTDVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SVecTDVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SVecTDVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector + , IsSparseVector, IsRowVector > + , SVecTSVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SVecTSVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SVecTSVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnVector > + , SVecTransExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , SVecTransExprTrait< Decay_ > + , 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::Type; + using Type2 = SVecTransExprTrait_; + \endcode +*/ +template< typename VT > // Type of the sparse vector +using SVecTransExprTrait_ = typename SVecTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , DMatSerialExprTrait + , TDMatSerialExprTrait > + , If_< IsRowMajorMatrix + , SMatSerialExprTrait + , TSMatSerialExprTrait > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsRowVector + , TDVecSerialExprTrait + , DVecSerialExprTrait > + , If_< IsRowVector + , TSVecSerialExprTrait + , SVecSerialExprTrait > > + , Failure > >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , SerialExprTrait< Decay_ > + , 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::Type; + using Type2 = SerialExprTrait_; + \endcode +*/ +template< typename T > // Type of the serial evaluation operand +using SerialExprTrait_ = typename SerialExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + , If_< IsMatrix + , If_< IsDenseMatrix + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , If_< IsRowMajorMatrix + , DMatDMatSubExprTrait + , DMatTDMatSubExprTrait > + , If_< IsRowMajorMatrix + , TDMatDMatSubExprTrait + , TDMatTDMatSubExprTrait > > + , If_< IsRowMajorMatrix + , If_< IsRowMajorMatrix + , DMatSMatSubExprTrait + , DMatTSMatSubExprTrait > + , If_< IsRowMajorMatrix + , TDMatSMatSubExprTrait + , TDMatTSMatSubExprTrait > > > + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , If_< IsRowMajorMatrix + , SMatDMatSubExprTrait + , SMatTDMatSubExprTrait > + , If_< IsRowMajorMatrix + , TSMatDMatSubExprTrait + , TSMatTDMatSubExprTrait > > + , If_< IsRowMajorMatrix + , If_< IsRowMajorMatrix + , SMatSMatSubExprTrait + , SMatTSMatSubExprTrait > + , If_< IsRowMajorMatrix + , TSMatSMatSubExprTrait + , TSMatTSMatSubExprTrait > > > > + , Failure > + , If_< IsVector + , If_< IsVector + , If_< IsDenseVector + , If_< IsDenseVector + , If_< IsRowVector + , If_< IsRowVector + , TDVecTDVecSubExprTrait + , Failure > + , If_< IsRowVector + , Failure + , DVecDVecSubExprTrait > > + , If_< IsRowVector + , If_< IsRowVector + , TDVecTSVecSubExprTrait + , Failure > + , If_< IsRowVector + , Failure + , DVecSVecSubExprTrait > > > + , If_< IsDenseVector + , If_< IsRowVector + , If_< IsRowVector + , TSVecTDVecSubExprTrait + , Failure > + , If_< IsRowVector + , Failure + , SVecDVecSubExprTrait > > + , If_< IsRowVector + , If_< IsRowVector + , TSVecTSVecSubExprTrait + , Failure > + , If_< IsRowVector + , Failure + , SVecSVecSubExprTrait > > > > + , Failure > + , If_< IsNumeric + , If_< IsNumeric + , SubTrait + , Failure > + , Failure > > >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = SubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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: +// +//
    +//
  • std::complex
  • +//
  • blaze::StaticVector
  • +//
  • blaze::HybridVector
  • +//
  • blaze::DynamicVector
  • +//
  • blaze::CustomVector
  • +//
  • blaze::CompressedVector
  • +//
  • blaze::StaticMatrix
  • +//
  • blaze::HybridMatrix
  • +//
  • blaze::DynamicMatrix
  • +//
  • blaze::CustomMatrix
  • +//
  • blaze::CompressedMatrix
  • +//
  • blaze::SymmetricMatrix
  • +//
  • blaze::HermitianMatrix
  • +//
  • blaze::LowerMatrix
  • +//
  • blaze::UniLowerMatrix
  • +//
  • blaze::StrictlyLowerMatrix
  • +//
  • blaze::UpperMatrix
  • +//
  • blaze::UniUpperMatrix
  • +//
  • blaze::StrictlyUpperMatrix
  • +//
  • blaze::DiagonalMatrix
  • +//
+// +// +// \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, DynamicVector > + { + typedef DynamicVector< typename SubTrait::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::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_; + using Type2 = Decay_; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + struct SubType { using Type = decltype( std::declval() - std::declval() ); }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , SubTrait + , 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, T2, EnableIf_< IsBuiltin > > +{ + public: + //********************************************************************************************** + using Type = CommonType_< complex , 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, EnableIf_< IsBuiltin > > +{ + public: + //********************************************************************************************** + using Type = CommonType_< T1, complex >; + //********************************************************************************************** +}; +/*! \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, complex > +{ + public: + //********************************************************************************************** + using Type = CommonType_< complex, complex >; + //********************************************************************************************** +}; +/*! \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::Type; + using Type2 = SubTrait_; + \endcode +*/ +template< typename T1, typename T2 > +using SubTrait_ = typename SubTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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::value,IsDenseMatrix::value>; }; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Tmp = RemoveReference_; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsComputation, IsTransExpr > + , If_< Or< IsConst, IsVolatile > + , SubmatrixExprTrait< RemoveCV_, AF > + , Failure > + , If_< IsMatrix + , Result + , 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::Type; + using Type2 = SubmatrixExprTrait_; + \endcode +*/ +template< typename MT // Type of the matrix operand + , bool AF > // Alignment flag +using SubmatrixExprTrait_ = typename SubmatrixExprTrait::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 +#include +#include +#include +#include +#include +#include + + +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: +// +//
    +//
  • blaze::StaticMatrix
  • +//
  • blaze::HybridMatrix
  • +//
  • blaze::DynamicMatrix
  • +//
  • blaze::CustomMatrix
  • +//
  • blaze::CompressedMatrix
  • +//
  • blaze::Submatrix
  • +//
+// +// +// \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 > + { + typedef DynamicMatrix 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 MatrixType1; + typedef typename SubmatrixTrait::Type ResultType1; + + // Definition of the result type of a column-major static matrix + typedef blaze::StaticMatrix MatrixType2; + typedef typename SubmatrixTrait::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, IsVolatile, IsReference > + , SubmatrixTrait< Decay_ > + , 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::Type; + using Type2 = SubmatrixTrait_; + \endcode +*/ +template< typename MT > // Type of the matrix +using SubmatrixTrait_ = typename SubmatrixTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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::value,IsDenseVector::value>; }; + /*! \endcond */ + //********************************************************************************************** + + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Tmp = RemoveReference_; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsComputation, IsTransExpr > + , If_< Or< IsConst, IsVolatile > + , SubvectorExprTrait< RemoveCV_, AF > + , Failure > + , If_< IsVector + , Result + , 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::Type; + using Type2 = SubvectorExprTrait_; + \endcode +*/ +template< typename VT // Type of the vector operand + , bool AF > // Alignment Flag +using SubvectorExprTrait_ = typename SubvectorExprTrait::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 +#include +#include +#include +#include +#include +#include + + +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: +// +//
    +//
  • blaze::StaticVector
  • +//
  • blaze::HybridVector
  • +//
  • blaze::DynamicVector
  • +//
  • blaze::CustomVector
  • +//
  • blaze::CompressedVector
  • +//
  • blaze::Subvector
  • +//
  • blaze::Row
  • +//
  • blaze::Column
  • +//
+// +// +// \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 > + { + typedef DynamicVector 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 VectorType1; + typedef typename SubvectorTrait::Type ResultType1; + + // Definition of the result type of the static row vector + typedef blaze::StaticVector VectorType2; + typedef typename SubvectorTrait::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, IsVolatile, IsReference > + , SubvectorTrait< Decay_ > + , 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::Type; + using Type2 = SubvectorTrait_; + \endcode +*/ +template< typename VT > // Type of the vector +using SubvectorTrait_ = typename SubvectorTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix > + , TDMatTransExprTrait< TDMatForEachExprTrait_ > + , Failure >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TDMatCTransExprTrait< Decay_ > + , 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::Type; + using Type2 = TDMatCTransExprTrait_; + \endcode +*/ +template< typename MT > // Type of the dense matrix +using TDMatCTransExprTrait_ = typename TDMatCTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , If_< IsSymmetric + , DMatDMatAddExpr< MT2, TDMatTransExprTrait_, false > + , If_< IsSymmetric + , DMatDMatAddExpr< DMatTransExprTrait_, MT1, true > + , DMatTDMatAddExpr > > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatDMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDMatDMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , TDMatDMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatDMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDMatDMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsDenseMatrix, IsRowMajorMatrix > + , If_< IsSymmetric + , DMatDMatSubExpr< TDMatTransExprTrait_, MT2, false > + , If_< IsSymmetric + , DMatDMatSubExpr< MT1, DMatTransExprTrait_, true > + , DMatTDMatSubExpr > > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatDMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDMatDMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsDenseVector, IsColumnVector > + , TDMatDVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatDVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDMatDVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix > + , DMatEvalExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TDMatEvalExprTrait< Decay_ > + , 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::Type; + using Type2 = TDMatEvalExprTrait_; + \endcode +*/ +template< typename MT > // Type of the dense matrix +using TDMatEvalExprTrait_ = typename TDMatEvalExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix > + , DMatForEachExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TDMatForEachExprTrait< Decay_, 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::Type; + using Type2 = TDMatForEachExprTrait_; + \endcode +*/ +template< typename MT // Type of the dense matrix + , typename OP > // Type of the custom operation +using TDMatForEachExprTrait_ = typename TDMatForEachExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix > + , DMatInvExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TDMatInvExprTrait< Decay_ > + , 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::Type; + using Type2 = TDMatInvExprTrait_; + \endcode +*/ +template< typename MT > // Type of the dense matrix +using TDMatInvExprTrait_ = typename TDMatInvExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , TDMatSMatAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatSMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDMatSMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , TDMatSMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatSMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDMatSMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , TDMatSMatSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatSMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDMatSMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsColumnMajorMatrix + , IsSparseVector, IsColumnVector > + , TDMatSVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatSVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDMatSVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , DivTrait_< UnderlyingBuiltin_, ST > + , DivTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< IsInvertible + , DMatScalarMultExpr + , DMatScalarDivExpr >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the TDMatScalarDivExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename MT + , typename ST > +struct TDMatScalarDivExprTraitHelper +{ + 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, IsColumnMajorMatrix, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatScalarDivExprTrait< Decay_, Decay_ > + , TDMatScalarDivExprTraitHelper >::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::Type; + using Type2 = TDMatScalarDivExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , MultTrait_< UnderlyingBuiltin_, ST > + , MultTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = DMatScalarMultExpr; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the TDMatScalarMultExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename MT + , typename ST > +struct TDMatScalarMultExprTraitHelper +{ + 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, IsColumnMajorMatrix, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatScalarMultExprTrait< Decay_, Decay_ > + , TDMatScalarMultExprTraitHelper >::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::Type; + using Type2 = TDMatScalarMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix > + , DMatSerialExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TDMatSerialExprTrait< Decay_ > + , 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::Type; + using Type2 = TDMatSerialExprTrait_; + \endcode +*/ +template< typename MT > // Type of the dense matrix +using TDMatSerialExprTrait_ = typename TDMatSerialExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , DMatDMatAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatTDMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDMatTDMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , TDMatTDMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatTDMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDMatTDMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsDenseMatrix, IsColumnMajorMatrix > + , DMatDMatSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatTDMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDMatTDMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , DMatSMatAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatTSMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDMatTSMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , TDMatTSMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatTSMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDMatTSMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , DMatSMatSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDMatTSMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDMatTSMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix > + , DMatTransExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TDMatTransExprTrait< Decay_ > + , 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::Type; + using Type2 = TDMatTransExprTrait_; + \endcode +*/ +template< typename MT > // Type of the dense matrix +using TDMatTransExprTrait_ = typename TDMatTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector > + , TDVecTransExprTrait< TDVecForEachExprTrait_ > + , Failure >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TDVecCTransExprTrait< Decay_ > + , 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::Type; + using Type2 = TDVecCTransExprTrait_; + \endcode +*/ +template< typename VT > // Type of the dense vector +using TDVecCTransExprTrait_ = typename TDVecCTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsDenseMatrix, IsRowMajorMatrix > + , TDVecDMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecDMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDVecDMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 +{ + //********************************************************************************************** + using Type = MultTrait_< ElementType_, ElementType_ >; + //********************************************************************************************** +}; +/*! \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::value && IsRowVector::value && + IsDenseVector::value && IsColumnVector::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecDVecMultExprTrait< Decay_, Decay_ > + , TDVecDVecMultExprTraitHelper >::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::Type; + using Type2 = TDVecDVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector > + , DVecEvalExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TDVecEvalExprTrait< Decay_ > + , 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::Type; + using Type2 = TDVecEvalExprTrait_; + \endcode +*/ +template< typename VT > // Type of the dense vector +using TDVecEvalExprTrait_ = typename TDVecEvalExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector > + , DVecForEachExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TDVecForEachExprTrait< Decay_, 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::Type; + using Type2 = TDVecForEachExprTrait_; + \endcode +*/ +template< typename VT // Type of the dense vector + , typename OP > // Type of the custom operation +using TDVecForEachExprTrait_ = typename TDVecForEachExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsRowVector + , IsSparseMatrix, IsRowMajorMatrix > + , If_< IsSymmetric + , TDVecTSMatMultExpr< VT, SMatTransExprTrait_ > + , TDVecSMatMultExpr > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecSMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDVecSMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 +{ + //********************************************************************************************** + using Type = MultTrait_< ElementType_, ElementType_ >; + //********************************************************************************************** +}; +/*! \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::value && IsRowVector::value && + IsSparseVector::value && IsColumnVector::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecSVecMultExprTrait< Decay_, Decay_ > + , TDVecSVecMultExprTraitHelper >::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::Type; + using Type2 = TDVecSVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , DivTrait_< UnderlyingBuiltin_, ST > + , DivTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< IsInvertible + , DVecScalarMultExpr + , DVecScalarDivExpr >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the TDVecScalarDivExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename VT + , typename ST > +struct TDVecScalarDivExprTraitHelper +{ + 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, IsRowVector, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecScalarDivExprTrait< Decay_, Decay_ > + , TDVecScalarDivExprTraitHelper >::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::Type; + using Type2 = TDVecScalarDivExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , MultTrait_< UnderlyingBuiltin_ ,ST > + , MultTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = DVecScalarMultExpr; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the TDVecScalarMultExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename VT + , typename ST > +struct TDVecScalarMultExprTraitHelper +{ + 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, IsRowVector, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecScalarMultExprTrait< Decay_, Decay_ > + , TDVecScalarMultExprTraitHelper >::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::Type; + using Type2 = TDVecScalarMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector > + , DVecSerialExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TDVecSerialExprTrait< Decay_ > + , 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::Type; + using Type2 = TDVecSerialExprTrait_; + \endcode +*/ +template< typename VT > // Type of the dense vector +using TDVecSerialExprTrait_ = typename TDVecSerialExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsDenseMatrix, IsColumnMajorMatrix > + , TDVecTDMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecTDMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDVecTDMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsDenseVector, IsRowVector > + , DVecDVecAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecTDVecAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDVecTDVecAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsDenseVector, IsRowVector > + , DVecDVecCrossExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecTDVecCrossExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDVecTDVecCrossExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsDenseVector, IsRowVector > + , DVecDVecDivExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecTDVecDivExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDVecTDVecDivExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsDenseVector, IsRowVector > + , DVecDVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecTDVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDVecTDVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsDenseVector, IsRowVector > + , DVecDVecSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecTDVecSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDVecTDVecSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix > + , TDVecTSMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecTSMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDVecTSMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsRowVector + , IsSparseVector, IsRowVector > + , DVecSVecAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecTSVecAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDVecTSVecAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsRowVector + , IsSparseVector, IsRowVector > + , DVecSVecCrossExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecTSVecCrossExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDVecTSVecCrossExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsRowVector + , IsSparseVector, IsRowVector > + , DVecSVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecTSVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDVecTSVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 , IsRowVector + , IsSparseVector, IsRowVector > + , DVecSVecSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TDVecTSVecSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TDVecTSVecSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector > + , DVecTransExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TDVecTransExprTrait< Decay_ > + , 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::Type; + using Type2 = TDVecTransExprTrait_; + \endcode +*/ +template< typename VT > // Type of the dense vector +using TDVecTransExprTrait_ = typename TDVecTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix > + , TSMatTransExprTrait< TSMatForEachExprTrait_ > + , Failure >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TSMatCTransExprTrait< Decay_ > + , 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::Type; + using Type2 = TSMatCTransExprTrait_; + \endcode +*/ +template< typename MT > // Type of the sparse matrix +using TSMatCTransExprTrait_ = typename TSMatCTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsDenseMatrix , IsRowMajorMatrix > + , DMatTSMatAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatDMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSMatDMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsDenseMatrix , IsRowMajorMatrix > + , TSMatDMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatDMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSMatDMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsDenseMatrix , IsRowMajorMatrix > + , TSMatDMatSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatDMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSMatDMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsDenseVector , IsColumnVector > + , If_< IsSymmetric + , SMatDVecMultExpr< TSMatTransExprTrait_, VT > + , TSMatDVecMultExpr > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatDVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSMatDVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix > + , SMatEvalExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TSMatEvalExprTrait< Decay_ > + , 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::Type; + using Type2 = TSMatEvalExprTrait_; + \endcode +*/ +template< typename MT > // Type of the sparse matrix +using TSMatEvalExprTrait_ = typename TSMatEvalExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix > + , SMatForEachExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TSMatForEachExprTrait< Decay_, 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::Type; + using Type2 = TSMatForEachExprTrait_; + \endcode +*/ +template< typename MT // Type of the sparse matrix + , typename OP > // Type of the custom operation +using TSMatForEachExprTrait_ = typename TSMatForEachExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , SMatTSMatAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatSMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSMatSMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , TSMatSMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatSMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSMatSMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsSparseMatrix, IsRowMajorMatrix > + , TSMatSMatSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatSMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSMatSMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsSparseVector, IsColumnVector > + , TSMatSVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatSVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSMatSVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , DivTrait_< UnderlyingBuiltin_, ST > + , DivTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< IsInvertible + , SMatScalarMultExpr + , SMatScalarDivExpr >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the TSMatScalarDivExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename MT + , typename ST > +struct TSMatScalarDivExprTraitHelper +{ + 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, IsColumnMajorMatrix, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatScalarDivExprTrait< Decay_, Decay_ > + , TSMatScalarDivExprTraitHelper >::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::Type; + using Type2 = TSMatScalarDivExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , MultTrait_< UnderlyingBuiltin_, ST > + , MultTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = SMatScalarMultExpr; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the TSMatScalarMultExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename MT + , typename ST > +struct TSMatScalarMultExprTraitHelper +{ + 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, IsColumnMajorMatrix, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatScalarMultExprTrait< Decay_, Decay_ > + , TSMatScalarMultExprTraitHelper >::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::Type; + using Type2 = TSMatScalarMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix > + , SMatSerialExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TSMatSerialExprTrait< Decay_ > + , 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::Type; + using Type2 = TSMatSerialExprTrait_; + \endcode +*/ +template< typename MT > // Type of the sparse matrix +using TSMatSerialExprTrait_ = typename TSMatSerialExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsDenseMatrix , IsColumnMajorMatrix > + , DMatSMatAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatTDMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSMatTDMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsDenseMatrix , IsColumnMajorMatrix > + , TSMatTDMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatTDMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSMatTDMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsDenseMatrix , IsColumnMajorMatrix > + , SMatDMatSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatTDMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSMatTDMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , TSMatTSMatAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatTSMatAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSMatTSMatAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , TSMatTSMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatTSMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSMatTSMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix + , IsSparseMatrix, IsColumnMajorMatrix > + , TSMatTSMatSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSMatTSMatSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSMatTSMatSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsColumnMajorMatrix > + , SMatTransExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TSMatTransExprTrait< Decay_ > + , 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::Type; + using Type2 = TSMatTransExprTrait_; + \endcode +*/ +template< typename MT > // Type of the sparse matrix +using TSMatTransExprTrait_ = typename TSMatTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector > + , TSVecTransExprTrait< TSVecForEachExprTrait_ > + , Failure >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TSVecCTransExprTrait< Decay_ > + , 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::Type; + using Type2 = TSVecCTransExprTrait_; + \endcode +*/ +template< typename VT > // Type of the sparse vector +using TSVecCTransExprTrait_ = typename TSVecCTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsDenseMatrix , IsRowMajorMatrix > + , TSVecDMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecDMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSVecDMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 +{ + //********************************************************************************************** + using Type = MultTrait_< ElementType_, ElementType_ >; + //********************************************************************************************** +}; +/*! \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::value && IsRowVector::value && + IsDenseVector::value && IsColumnVector::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecDVecMultExprTrait< Decay_, Decay_ > + , TSVecDVecMultExprTraitHelper >::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::Type; + using Type2 = TSVecDVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector > + , SVecEvalExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TSVecEvalExprTrait< Decay_ > + , 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::Type; + using Type2 = TSVecEvalExprTrait_; + \endcode +*/ +template< typename VT > // Type of the sparse vector +using TSVecEvalExprTrait_ = typename TSVecEvalExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector > + , SVecForEachExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TSVecForEachExprTrait< Decay_, 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::Type; + using Type2 = TSVecForEachExprTrait_; + \endcode +*/ +template< typename VT // Type of the sparse vector + , typename OP > // Type of the custom operation +using TSVecForEachExprTrait_ = typename TSVecForEachExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsSparseMatrix, IsRowMajorMatrix > + , TSVecSMatMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecSMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSVecSMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 +{ + //********************************************************************************************** + using Type = MultTrait_< ElementType_, ElementType_ >; + //********************************************************************************************** +}; +/*! \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::value && IsRowVector::value && + IsSparseVector::value && IsColumnVector::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecSVecMultExprTrait< Decay_, Decay_ > + , TSVecSVecMultExprTraitHelper >::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::Type; + using Type2 = TSVecSVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , DivTrait_< UnderlyingBuiltin_ ,ST > + , DivTrait_< UnderlyingNumeric_, ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = If_< IsInvertible + , SVecScalarMultExpr + , SVecScalarDivExpr >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the TSVecScalarDivExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename VT + , typename ST > +struct TSVecScalarDivExprTraitHelper +{ + 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, IsRowVector, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecScalarDivExprTrait< Decay_, Decay_ > + , TSVecScalarDivExprTraitHelper >::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::Type; + using Type2 = TSVecScalarDivExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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_ >, IsBuiltin > + , MultTrait_< UnderlyingBuiltin_, ST > + , MultTrait_< UnderlyingNumeric_ ,ST > >; + //********************************************************************************************** + + public: + //********************************************************************************************** + using Type = SVecScalarMultExpr; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the TSVecScalarMultExprTraitHelper class template. +// \ingroup math_traits +*/ +template< typename VT + , typename ST > +struct TSVecScalarMultExprTraitHelper +{ + 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, IsRowVector, IsNumeric >::value }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecScalarMultExprTrait< Decay_, Decay_ > + , TSVecScalarMultExprTraitHelper >::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::Type; + using Type2 = TSVecScalarMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector > + , SVecSerialExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TSVecSerialExprTrait< Decay_ > + , 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::Type; + using Type2 = TSVecSerialExprTrait_; + \endcode +*/ +template< typename VT > // Type of the sparse vector +using TSVecSerialExprTrait_ = typename TSVecSerialExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsDenseMatrix , IsColumnMajorMatrix > + , If_< IsSymmetric + , TSVecDMatMultExpr< VT, TDMatTransExprTrait_ > + , TSVecTDMatMultExpr > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecTDMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSVecTDMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsDenseVector , IsRowVector > + , DVecSVecAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecTDVecAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSVecTDVecAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsDenseVector , IsRowVector > + , SVecDVecCrossExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecTDVecCrossExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSVecTDVecCrossExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsDenseVector , IsRowVector > + , SVecDVecDivExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecTDVecDivExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSVecTDVecDivExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsDenseVector , IsRowVector > + , SVecDVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecTDVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSVecTDVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsDenseVector , IsRowVector > + , SVecDVecSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecTDVecSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSVecTDVecSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsSparseMatrix, IsColumnMajorMatrix > + , If_< IsSymmetric + , TSVecSMatMultExpr< VT, TSMatTransExprTrait_ > + , TSVecTSMatMultExpr > + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecTSMatMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSVecTSMatMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsSparseVector, IsRowVector > + , SVecSVecAddExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecTSVecAddExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSVecTSVecAddExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsSparseVector, IsRowVector > + , SVecSVecCrossExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecTSVecCrossExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSVecTSVecCrossExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsSparseVector, IsRowVector > + , SVecSVecMultExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecTSVecMultExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSVecTSVecMultExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector + , IsSparseVector, IsRowVector > + , SVecSVecSubExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference + , IsConst, IsVolatile, IsReference > + , TSVecTSVecSubExprTrait< Decay_, Decay_ > + , 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::Type; + using Type2 = TSVecTSVecSubExprTrait_; + \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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsRowVector > + , SVecTransExpr + , INVALID_TYPE >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TSVecTransExprTrait< Decay_ > + , 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::Type; + using Type2 = TSVecTransExprTrait_; + \endcode +*/ +template< typename VT > // Type of the sparse vector +using TSVecTransExprTrait_ = typename TSVecTransExprTrait::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + , If_< IsDenseMatrix + , If_< IsRowMajorMatrix + , DMatTransExprTrait + , TDMatTransExprTrait > + , If_< IsRowMajorMatrix + , SMatTransExprTrait + , TSMatTransExprTrait > > + , If_< IsVector + , If_< IsDenseVector + , If_< IsRowVector + , TDVecTransExprTrait + , DVecTransExprTrait > + , If_< IsRowVector + , TSVecTransExprTrait + , SVecTransExprTrait > > + , Failure > >; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using Type = typename If_< Or< IsConst, IsVolatile, IsReference > + , TransExprTrait< Decay_ > + , 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::Type; + using Type2 = TransExprTrait_; + \endcode +*/ +template< typename T > // Type of the transpose operand +using TransExprTrait_ = typename TransExprTrait::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 +#include +#include +#include + + +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::value && + AreSIMDCombinableHelper::value }; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the AreSIMDCombinableHelper class template for two matching types. +template< typename T > +struct AreSIMDCombinableHelper +{ + enum : bool { value = IsNumeric::value }; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the AreSIMDCombinableHelper class template for two different types. +template< typename T1, typename T2 > +struct AreSIMDCombinableHelper +{ + enum : bool { value = IsNumeric::value && IsIntegral::value && + IsNumeric::value && IsIntegral::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, complex > // Is derived from TrueType + blaze::AreSIMDCombinable< int, float >::value // Evaluates to 0 + blaze::AreSIMDCombinable< double, float >::Type // Results in FalseType + blaze::AreSIMDCombinable< complex, complex > // Is derived from FalseType + \endcode +*/ +template< typename T1, typename T2, typename... Args > +struct AreSIMDCombinable + : public BoolConstant< AreSIMDCombinableHelper< T1, T2, Decay_... >::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 +#include + + +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 >::value // Evaluates to 2 + blaze::Columns< HybridMatrix >::value // Evaluates to 0; Only maximum number of columns is fixed! + blaze::Columns< DynamicMatrix >::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::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::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::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 +#include + + +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 >::value // Evaluates to 1 + blaze::HasConstDataAccess< const DynamicVector >::Type // Results in TrueType + blaze::HasConstDataAccess< volatile DynamicMatrix > // Is derived from TrueType + blaze::HasConstDataAccess< int >::value // Evaluates to 0 + blaze::HasConstDataAccess< const CompressedVector >::Type // Results in FalseType + blaze::HasConstDataAccess< volatile CompressedMatrix > // 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include + + +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 >::value // Evaluates to 1 + blaze::HasMutableDataAccess< const DynamicVector >::Type // Results in TrueType + blaze::HasMutableDataAccess< volatile DynamicMatrix > // Is derived from TrueType + blaze::HasMutableDataAccess< int >::value // Evaluates to 0 + blaze::HasMutableDataAccess< const CompressedVector >::Type // Results in FalseType + blaze::HasMutableDataAccess< volatile CompressedMatrix > // 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsIntegral, IsSigned > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDAbs : public BoolConstant< HasSIMDAbsHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDAcos : public BoolConstant< HasSIMDAcosHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDAcosh : public BoolConstant< HasSIMDAcoshHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include +#include + + +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, IsIntegral + , IsNumeric, IsIntegral + , 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, complex, EnableIf_< And< IsNumeric, IsIntegral > > > +{ + 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, complex > +{ + 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, complex > +{ + 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_, Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDAsin : public BoolConstant< HasSIMDAsinHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDAsinh : public BoolConstant< HasSIMDAsinhHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDAtan : public BoolConstant< HasSIMDAtanHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDAtanh : public BoolConstant< HasSIMDAtanhHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDCbrt : public BoolConstant< HasSIMDCbrtHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ +#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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDCeil : public BoolConstant< HasSIMDCeilHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITION +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T // Type of the operand + , typename = void > // Restricting condition +struct HasSIMDConjHelper +{ + enum : bool { value = IsNumeric::value }; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename T > +struct HasSIMDConjHelper< complex > +{ + enum : bool { value = IsNumeric::value && IsSigned::value && HasSIMDMult::value && + ( IsFloatingPoint::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 > // Is derived from TrueType + blaze::HasSIMDConj< complex >::value // Evaluates to 0 + blaze::HasSIMDConj< complex >::Type // Results in FalseType + blaze::HasSIMDConj< complex > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDConj : public BoolConstant< HasSIMDConjHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDCos : public BoolConstant< HasSIMDCosHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDCosh : public BoolConstant< HasSIMDCoshHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include +#include +#include + + +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, IsIntegral, IsSigned + , IsNumeric, IsIntegral, IsSigned + , Bool< sizeof(T1) == sizeof(T2) > > > > +{ + enum : bool { value = bool( BLAZE_MIC_MODE ) && sizeof(T1) >= 4UL }; +}; + +template< typename T > +struct HasSIMDDivHelper< complex, T, EnableIf_< And< IsNumeric, IsIntegral, IsSigned > > > +{ + 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 > // 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_, Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDErf : public BoolConstant< HasSIMDErfHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDErfc : public BoolConstant< HasSIMDErfcHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDExp : public BoolConstant< HasSIMDExpHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ +#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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDFloor : public BoolConstant< HasSIMDFloorHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDInvCbrt : public BoolConstant< HasSIMDInvCbrtHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDInvSqrt : public BoolConstant< HasSIMDInvSqrtHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDLog : public BoolConstant< HasSIMDLogHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDLog10 : public BoolConstant< HasSIMDLog10Helper< Decay_ >::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 +#include +#include +#include +#include +#include +#include +#include + + +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, IsIntegral + , IsNumeric, IsIntegral + , 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, complex, EnableIf_< And< IsNumeric, IsIntegral > > > +{ + 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, complex > +{ + 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, complex > +{ + 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 > // 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_, Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDPow : public BoolConstant< HasSIMDPowHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDSin : public BoolConstant< HasSIMDSinHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDSinh : public BoolConstant< HasSIMDSinhHelper< Decay_ >::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 +#include +#include + + +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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDSqrt : public BoolConstant< HasSIMDSqrtHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include +#include + + +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, IsIntegral + , IsNumeric, IsIntegral + , 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, complex, EnableIf_< And< IsNumeric, IsIntegral > > > +{ + 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, complex > +{ + 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, complex > +{ + 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_, Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDTan : public BoolConstant< HasSIMDTanHelper< Decay_ >::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 +#include +#include +#include +#include +#include +#include + + +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, IsDouble > > > +{ + 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > // Type of the operand +struct HasSIMDTanh : public BoolConstant< HasSIMDTanhHelper< Decay_ >::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 +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::LowerMatrix LowerStaticType; + typedef blaze::UpperMatrix UpperDynamicType; + typedef blaze::SymmetricMatrix 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include + + +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 >::value // Evaluates to 1 + blaze::IsAligned< const DynamicMatrix >::Type // Results in TrueType + blaze::IsAligned< volatile CustomVector > // Is derived from TrueType + blaze::IsAligned< CompressedVector >::value // Evaluates to 0 + blaze::IsAligned< const CustomVector >::Type // Results in FalseType + blaze::IsAligned< volatile CustomMatrix > // 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include +#include +#include + + +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 and +// \c complex 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 > // 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, IsDouble, IsComplexFloat, IsComplexDouble >::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 +#include +#include + + +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 DenseMatrixType1; + typedef blaze::Column DenseColumnType1; + + typedef blaze::StaticMatrix DenseMatrixType2; + typedef blaze::Column DenseColumnType2; + + typedef blaze::CompressedMatrix SparseMatrixType; + typedef blaze::Column 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 > : 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 > : 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 > : 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 > : 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 +#include +#include +#include + + +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 >::value // Evaluates to 1 + blaze::IsColumnMajorMatrix< const DynamicMatrix >::Type // Results in TrueType + blaze::IsColumnMajorMatrix< volatile CompressedMatrix > // Is derived from TrueType + blaze::IsColumnMajorMatrix< StaticMatrix >::value // Evaluates to 0 + blaze::IsColumnMajorMatrix< const DynamicMatrix >::Type // Results in FalseType + blaze::IsColumnMajorMatrix< volatile CompressedMatrix > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsColumnMajorMatrix + : public BoolConstant< IsBaseOf,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 +#include +#include +#include + + +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 >::value // Evaluates to 1 + blaze::IsColumnVector< const DynamicVector >::Type // Results in TrueType + blaze::IsColumnVector< volatile CompressedVector > // Is derived from TrueType + blaze::IsColumnVector< StaticVector >::value // Evaluates to 0 + blaze::IsColumnVector< const DynamicVector >::Type // Results in FalseType + blaze::IsColumnVector< volatile CompressedVector > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsColumnVector + : public BoolConstant< IsBaseOf,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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include + + +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 CustomVectorType; + typedef CustomMatrix 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 >::Type // Results in FalseType + blaze::IsCustom< volatile DynamicMatrix > // 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include +#include + + +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 >::value // Evaluates to 1 + blaze::IsDenseMatrix< const DynamicMatrix >::Type // Results in TrueType + blaze::IsDenseMatrix< volatile DynamicMatrix > // Is derived from TrueType + blaze::IsDenseMatrix< CompressedMatrix::value // Evaluates to 0 + blaze::IsDenseMatrix< CompressedVector >::Type // Results in FalseType + blaze::IsDenseMatrix< DynamicVector > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsDenseMatrix + : public BoolConstant< Or< IsBaseOf,false>,T> + , IsBaseOf,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 +#include +#include +#include +#include + + +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 >::value // Evaluates to 1 + blaze::IsDenseVector< const StaticVector >::Type // Results in TrueType + blaze::IsDenseVector< volatile StaticVector > // Is derived from TrueType + blaze::IsDenseVector< CompressedVector >::value // Evaluates to 0 + blaze::IsDenseVector< CompressedMatrix >::Type // Results in FalseType + blaze::IsDenseVector< DynamicMatrix > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsDenseVector + : public BoolConstant< Or< IsBaseOf,false>,T> + , IsBaseOf,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 +#include +#include +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::DiagonalMatrix DiagonalStaticType; + typedef blaze::DiagonalMatrix DiagonalDynamicType; + typedef blaze::DiagonalMatrix DiagonalCompressedType; + + typedef blaze::LowerMatrix LowerStaticType; + typedef blaze::UpperMatrix 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, IsUpper >::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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::SymmetricMatrix SymmetricStaticType; + typedef blaze::HermitianMatrix HermitianDynamicType; + typedef blaze::LowerMatrix 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 >, Not< IsHermitian >, Not< IsTriangular > >::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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::HermitianMatrix HermitianStaticType; + typedef blaze::HermitianMatrix HermitianDynamicType; + typedef blaze::HermitianMatrix 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::IdentityMatrix IdentityStaticType; + typedef blaze::IdentityMatrix IdentityDynamicType; + typedef blaze::IdentityMatrix IdentityCompressedType; + + typedef blaze::LowerMatrix LowerStaticType; + typedef blaze::UpperMatrix 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, IsUniUpper >::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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include +#include +#include +#include + + +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, or \c complex), long double, 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 >::Type // Results in TrueType + blaze::IsInvertible< blaze::DynamicMatrix > // Is derived from TrueType + blaze::IsInvertible< int >::value // Evaluates to 0 + blaze::IsInvertible< complex >::Type // Results in FalseType + blaze::IsInvertible< blaze::DynamicVector > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsInvertible + : public BoolConstant< Or< IsBLASCompatible + , IsLongDouble + , And< IsDenseMatrix + , IsBLASCompatible< UnderlyingElement_ > > + >::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 +#include +#include +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::LowerMatrix LowerStaticType; + typedef blaze::LowerMatrix LowerDynamicType; + typedef blaze::UniLowerMatrix 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, IsStrictlyLower >::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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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 >::value // Evaluates to 1 + blaze::IsMatrix< const DynamicMatrix >::Type // Results in TrueType + blaze::IsMatrix< volatile CompressedMatrix > // Is derived from TrueType + blaze::IsMatrix< StaticVector >::value // Evaluates to 0 + blaze::IsMatrix< const DynamicVector >::Type // Results in FalseType + blaze::IsMatrix< volatile CompressedVector > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsMatrix + : public BoolConstant< Or< IsBaseOf,false>,T> + , IsBaseOf,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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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 Type1; + typedef CompressedMatrix< complex > Type2; + typedef LowerMatrix< DynamicMatrix > Type3; + + typedef double Type4; + typedef DynamicVector Type5; + typedef DynamicMatrix< DynamicVector > 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, IsNumeric< UnderlyingElement_ > >::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 +#include +#include +#include +#include + + +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 Type1; + typedef StaticVector Type2; + typedef HybridVector< complex > Type3; + + typedef double Type4; + typedef DynamicMatrix Type5; + typedef DynamicVector< DynamicVector > 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, IsNumeric< UnderlyingElement_ > >::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 +#include + + +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 DenseColumnMajor; + typedef blaze::CompressedMatrix SparseRowMajor; + + blaze::IsOpposedView< Row >::value // Evaluates to 1 + blaze::IsOpposedView< Column >::Type // Results in TrueType + blaze::IsOpposedView< const volatile Row > // Is derived from TrueType + blaze::IsOpposedView< Column >::value // Evaluates to 0 + blaze::IsOpposedView< Row >::Type // Results in FalseType + blaze::IsOpposedView< const volatile Row > // 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include + + +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 >::value // Evaluates to 1 + blaze::IsPadded< const blaze::HybridVector >::Type // Results in TrueType + blaze::IsPadded< volatile blaze::DynamicMatrix > // Is derived from TrueType + blaze::IsPadded< int >::value // Evaluates to 0 + blaze::IsPadded< const CompressedVector >::Type // Results in FalseType + blaze::IsPadded< volatile CompressedMatrix > // 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include + + +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& ); + + static No test( ... ); + //********************************************************************************************** + + public: + //********************************************************************************************** + static constexpr bool value = ( sizeof( test( std::declval< RemoveCV_ >() ) ) == 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 {}; + class MyProxy2 : public Proxy {}; + class MyProxy3 : public Proxy {}; + 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::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 +#include + + +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 >::value // Evaluates to 1 + blaze::IsResizable< const DynamicMatrix >::Type // Results in TrueType + blaze::IsResizable< volatile CompressedMatrix > // Is derived from TrueType + blaze::IsResizable< int >::value // Evaluates to 0 + blaze::IsResizable< const complex >::Type // Results in FalseType + blaze::IsResizable< volatile StaticVector > // 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include + + +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 VectorType; + typedef blaze::DynamicMatrix MatrixType; + + typedef blaze::LowerMatrix< blaze::DynamicMatrix > Lower; + typedef blaze::LowerMatrix< blaze::CompressedMatrix > 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include + + +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 DenseMatrixType1; + typedef blaze::Row DenseRowType1; + + typedef blaze::StaticMatrix DenseMatrixType2; + typedef blaze::Row DenseRowType2; + + typedef blaze::CompressedMatrix SparseMatrixType; + typedef blaze::Row 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 > : 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 > : 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 > : 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 > : 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 +#include +#include +#include + + +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 >::value // Evaluates to 1 + blaze::IsRowMajorMatrix< const DynamicMatrix >::Type // Results in TrueType + blaze::IsRowMajorMatrix< volatile CompressedMatrix > // Is derived from TrueType + blaze::IsRowMajorMatrix< StaticMatrix >::value // Evaluates to 0 + blaze::IsRowMajorMatrix< const DynamicMatrix >::Type // Results in FalseType + blaze::IsRowMajorMatrix< volatile CompressedMatrix > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsRowMajorMatrix + : public BoolConstant< IsBaseOf,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 +#include +#include +#include + + +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 >::value // Evaluates to 1 + blaze::IsRowVector< const DynamicVector >::Type // Results in TrueType + blaze::IsRowVector< volatile CompressedVector > // Is derived from TrueType + blaze::IsRowVector< StaticVector >::value // Evaluates to 0 + blaze::IsRowVector< const DynamicVector >::Type // Results in FalseType + blaze::IsRowVector< volatile CompressedVector > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsRowVector + : public BoolConstant< IsBaseOf,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 +#include +#include +#include +#include + + +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, IsMatrix > + , UseNestedMember + , NotSIMDEnabled + >::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::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 +#include +#include +#include +#include + + +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: +// +//
    +//
  • Basic SIMD packed data types:
  • +//
      +//
    • SIMDint8
    • +//
    • SIMDint16
    • +//
    • SIMDint32
    • +//
    • SIMDint64
    • +//
    • SIMDfloat
    • +//
    • SIMDdouble
    • +//
    • SIMDcint8
    • +//
    • SIMDcint16
    • +//
    • SIMDcint32
    • +//
    • SIMDcint64
    • +//
    • SIMDcfloat
    • +//
    • SIMDcdouble
    • +//
    +//
  • Derived SIMD packed data types:
  • +//
      +//
    • SIMDshort
    • +//
    • SIMDushort
    • +//
    • SIMDint
    • +//
    • SIMDuint
    • +//
    • SIMDlong
    • +//
    • SIMDulong
    • +//
    • SIMDcshort
    • +//
    • SIMDcushort
    • +//
    • SIMDcint
    • +//
    • SIMDcuint
    • +//
    • SIMDclong
    • +//
    • SIMDculong
    • +//
    +//
+// +// 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 > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsSIMDPack + : public BoolConstant< Or< IsBaseOf >,T> + , IsBaseOf >,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 +#include +#include +#include +#include + + +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, IsMatrix > + , UseNestedMember + , NotSMPAssignable + >::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 VectorType; + typedef blaze::Subvector SubvectorType; + + blaze::IsSMPAssignable< VectorType >::value // Evaluates to 1 + blaze::IsSMPAssignable< SubvectorType >::Type // Results in TrueType + blaze::IsSMPAssignable< DynamicMatrix > // Is derived from TrueType + blaze::IsSMPAssignable< int >::value // Evaluates to 0 + blaze::IsSMPAssignable< StaticVector >::Type // Results in FalseType + blaze::IsSMPAssignable< StaticMatrix > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsSMPAssignable : public BoolConstant< IsSMPAssignableHelper::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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 >::value // Evaluates to 1 + blaze::IsSparseMatrix< const CompressedMatrix >::Type // Results in TrueType + blaze::IsSparseMatrix< volatile CompressedMatrix > // Is derived from TrueType + blaze::IsSparseMatrix< DynamicVector >::value // Evaluates to 0 + blaze::IsSparseMatrix< const DynamicMatrix >::Type // Results in FalseType + blaze::IsSparseMatrix< CompressedVector > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsSparseMatrix + : public BoolConstant< Or< IsBaseOf,false>,T> + , IsBaseOf,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 +#include +#include +#include +#include + + +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 >::value // Evaluates to 1 + blaze::IsSparseVector< const CompressedVector >::Type // Results in TrueType + blaze::IsSparseVector< volatile CompressedVector > // Is derived from TrueType + blaze::IsSparseVector< DynamicVector >::value // Evaluates to 0 + blaze::IsSparseVector< const DynamicMatrix >::Type // Results in FalseType + blaze::IsSparseVector< CompressedMatrix > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsSparseVector + : public BoolConstant< Or< IsBaseOf,false>,T> + , IsBaseOf,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 +#include + + +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 Mat2x2; + typedef blaze::StaticMatrix Mat3x3; + typedef blaze::StaticMatrix Mat4x4; + + // Type definitions of non-square matrix types + typedef blaze::StaticMatrix Mat2x3; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::HybridMatrix 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::StrictlyLowerMatrix StrictlyLowerStaticType; + typedef blaze::StrictlyLowerMatrix StrictlyLowerDynamicType; + typedef blaze::StrictlyLowerMatrix 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::StrictlyLowerMatrix StrictlyLowerStaticType; + typedef blaze::StrictlyUpperMatrix StrictlyUpperDynamicType; + typedef blaze::StrictlyLowerMatrix 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, IsStrictlyUpper >::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 +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::StrictlyUpperMatrix StrictlyUpperStaticType; + typedef blaze::StrictlyUpperMatrix StrictlyUpperDynamicType; + typedef blaze::StrictlyUpperMatrix 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include + + +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 DenseMatrixType1; + typedef blaze::Submatrix DenseSubmatrixType1; + + typedef blaze::StaticMatrix DenseMatrixType2; + typedef blaze::Submatrix DenseSubmatrixType2; + + typedef blaze::CompressedMatrix SparseMatrixType; + typedef blaze::Submatrix 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 > : 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 > : 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 > : 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 > : 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 +#include +#include + + +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 DenseVectorType1; + typedef blaze::Subvector DenseSubvectorType1; + + typedef blaze::StaticVector DenseVectorType2; + typedef blaze::Subvector DenseSubvectorType2; + + typedef blaze::CompressedVector SparseVectorType; + typedef blaze::Subvector 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 > : 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 > : 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 > : 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 > : 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 +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::SymmetricMatrix SymmetricStaticType; + typedef blaze::SymmetricMatrix SymmetricDynamicType; + typedef blaze::SymmetricMatrix 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include +#include + + +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 >, Not< IsNumeric >, Not< IsExpression > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::LowerMatrix LowerStaticType; + typedef blaze::UpperMatrix UpperDynamicType; + typedef blaze::LowerMatrix 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, IsUpper >::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 +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::UniLowerMatrix UniLowerStaticType; + typedef blaze::UniLowerMatrix UniLowerDynamicType; + typedef blaze::UniLowerMatrix 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::UniLowerMatrix UniLowerStaticType; + typedef blaze::UniUpperMatrix UniUpperDynamicType; + typedef blaze::UniLowerMatrix 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, IsUniUpper >::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 +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::UniUpperMatrix UniUpperStaticType; + typedef blaze::UniUpperMatrix UniUpperDynamicType; + typedef blaze::UniUpperMatrix 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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include + + +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 StaticMatrixType; + typedef blaze::DynamicMatrix DynamicMatrixType; + typedef blaze::CompressedMatrix CompressedMatrixType; + + typedef blaze::UpperMatrix UpperStaticType; + typedef blaze::UpperMatrix UpperDynamicType; + typedef blaze::UniUpperMatrix 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, IsStrictlyUpper >::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 +{}; +/*! \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 +{}; +/*! \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 +{}; +/*! \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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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, Not< IsBaseOf > >::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 +#include +#include +#include +#include + + +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 >::value // Evaluates to 1 + blaze::IsVector< const DynamicVector >::Type // Results in TrueType + blaze::IsVector< volatile CompressedVector > // Is derived from TrueType + blaze::IsVector< StaticMatrix >::value // Evaluates to 0 + blaze::IsVector< const DynamicMatrix >::Type // Results in FalseType + blaze::IsVector< volatile CompressedMatrix > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsVector + : public BoolConstant< Or< IsBaseOf,false>,T> + , IsBaseOf,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 +#include +#include +#include +#include + + +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 VectorType; + typedef blaze::Subvector SubvectorType; + + typedef blaze::CompressedMatrix MatrixType; + typedef blaze::Row RowType; + typedef blaze::Column 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, Not< IsBaseOf > >::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 > SymmetricDynamic; + typedef LowerMatrix< CompressedMatrix > LowerCompressed; + typedef UpperMatrix< DynamicMatrix > UpperDynamic; + + blaze::RemoveAdaptor< SymmetricDynamic >::Type // Results in 'DynamicMatrix' + blaze::RemoveAdaptor< const LowerCompressed >::Type // Results in 'const CompressedMatrix' + blaze::RemoveAdaptor< volatile UpperDynamic >::Type // Results in 'volatile DynamicMatrix' + blaze::RemoveAdaptor< int >::Type // Results in 'int' + blaze::RemoveAdaptor< const DynamicVector >::Type // Results in 'const DynamicVector' + blaze::RemoveAdaptor< volatile DynamicMatrix >::Type // Results in 'volatile DynamicMatrix' + \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::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::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::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::Type; + using Type2 = RemoveAdaptor_; + \endcode +*/ +template< typename T > +using RemoveAdaptor_ = typename RemoveAdaptor::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 +#include +#include + + +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 >::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 +#include + + +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 >::value // Evaluates to 3 + blaze::Rows< HybridMatrix >::value // Evaluates to 0; Only maximum number of rows is fixed! + blaze::Rows< DynamicMatrix >::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::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::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::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 +#include + + +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 >::value // Evaluates to 3 + blaze::Size< HybridVector >::value // Evaluates to 0; Only maximum size is fixed! + blaze::Size< DynamicVector >::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::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::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::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 +#include +#include +#include +#include + + +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 RowMajorMatrix; + typedef blaze::DynamicMatrix ColumnMajorMatrix; + + blaze::StorageOrder::value // Evaluates to blaze::rowMajor + blaze::StorageOrder::value // Evaluates to blaze::columnMajor + blaze::StorageOrder::value // Compilation error! + \endcode +*/ +template< typename T, typename = EnableIf_< IsMatrix > > +struct StorageOrder : public BoolConstant< ( IsRowMajorMatrix::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 +#include +#include +#include +#include + + +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 RowVector; + typedef blaze::DynamicVector ColumnVector; + + blaze::TransposeFlag::value // Evaluates to blaze::rowVector + blaze::TransposeFlag::value // Evaluates to blaze::columnVector + blaze::TransposeFlag::value // Compilation error! + \endcode +*/ +template< typename T, typename = EnableIf_< IsVector > > +struct TransposeFlag : public BoolConstant< ( IsRowVector::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 +#include +#include + + +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 Type2; // Complex data type + typedef StaticVector Type3; // Vector with built-in element type + typedef CompressedVector< DynamicVector > 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::Type Type; }; + /*! \endcond */ + //********************************************************************************************** + + //**struct Other******************************************************************************** + /*! \cond BLAZE_INTERNAL */ + template< typename T2 > + struct Other { typedef typename UnderlyingBuiltin::Type Type; }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename If_< IsBuiltin + , Builtin + , If_< IsComplex + , Complex + , Other > + >::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::Type; + using Type2 = UnderlyingBuiltin_; + \endcode +*/ +template< typename T > +using UnderlyingBuiltin_ = typename UnderlyingBuiltin::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 +#include +#include +#include + + +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 Type2; // Complex data type + typedef StaticVector Type3; // Vector with built-in element type + typedef CompressedMatrix< DynamicVector > 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 + \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 + , Builtin + , If_< IsComplex + , Complex + , Other > + >::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::Type; + using Type2 = UnderlyingElement_; + \endcode +*/ +template< typename T > +using UnderlyingElement_ = typename UnderlyingElement::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 +#include +#include +#include + + +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 Type2; // Complex data type + typedef StaticVector Type3; // Vector with built-in element type + typedef CompressedVector< DynamicVector > Type4; // Vector with vector element type + + blaze::UnderlyingNumeric< Type1 >::Type // corresponds to double + blaze::UnderlyingNumeric< Type2 >::Type // corresponds to complex + 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::Type Type; }; + /*! \endcond */ + //********************************************************************************************** + + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename If_< Or< IsBuiltin, IsComplex > + , BuiltinOrComplex + , Other + >::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::Type; + using Type2 = UnderlyingNumeric_; + \endcode +*/ +template< typename T > +using UnderlyingNumeric_ = typename UnderlyingNumeric::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 DenseMatrix; + typedef blaze::CompressedMatrix SparseMatrix; + + DenseMatrix D; + SparseMatrix S; + // ... Resizing and initialization + + // Creating a view on the 3rd column of the dense matrix D + blaze::Column = column( D, 3UL ); + + // Creating a view on the 4th column of the sparse matrix S + blaze::Column = column( S, 4UL ); + \endcode +*/ +template< typename MT // Type of the matrix + , bool SO > // Storage order +inline DisableIf_< Or< IsComputation, IsTransExpr >, ColumnExprTrait_ > + column( Matrix& matrix, size_t index ) +{ + BLAZE_FUNCTION_TRACE; + + return ColumnExprTrait_( ~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 DenseMatrix; + typedef blaze::CompressedMatrix SparseMatrix; + + DenseMatrix D; + SparseMatrix S; + // ... Resizing and initialization + + // Creating a view on the 3rd column of the dense matrix D + blaze::Column = column( D, 3UL ); + + // Creating a view on the 4th column of the sparse matrix S + blaze::Column = column( S, 4UL ); + \endcode +*/ +template< typename MT // Type of the matrix + , bool SO > // Storage order +inline DisableIf_< Or< IsComputation, IsTransExpr >, ColumnExprTrait_ > + column( const Matrix& matrix, size_t index ) +{ + BLAZE_FUNCTION_TRACE; + + return ColumnExprTrait_( ~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, ColumnExprTrait_ > + column( const Matrix& 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, ColumnExprTrait_ > + column( const Matrix& 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, ColumnExprTrait_ > + column( const Matrix& 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, ColumnExprTrait_ > + column( const Matrix& 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, ColumnExprTrait_ > + column( const Matrix& 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, ColumnExprTrait_ > + column( const Matrix& 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, ColumnExprTrait_ > + column( const Matrix& 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, ColumnExprTrait_ > + column( const Matrix& 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, ColumnExprTrait_ > + column( const Matrix& 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, ColumnExprTrait_ > + column( const Matrix& 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& column ); + +template< typename MT, bool SO, bool DF, bool SF > +inline void clear( Column& column ); + +template< typename MT, bool SO, bool DF, bool SF > +inline bool isDefault( const Column& column ); + +template< typename MT, bool SO, bool DF, bool SF > +inline bool isIntact( const Column& column ) noexcept; + +template< typename MT, bool SO, bool DF, bool SF > +inline bool isSame( const Column& a, const Column& 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& 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& 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 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& column ) +{ + for( size_t i=0UL; i 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& column ) +{ + typedef ConstIterator_< Column > 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 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& 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& a, const Column& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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 > derestrict( Column& column ) +{ + typedef DerestrictTrait_< Column > 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 > : public BoolConstant< IsRestricted::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DERESTRICTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool SF > +struct DerestrictTrait< Column > +{ + using Type = Column< RemoveReference_< DerestrictTrait_ > >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool SF > +struct HasConstDataAccess< Column > + : public BoolConstant< HasConstDataAccess::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool SF > +struct HasMutableDataAccess< Column > + : public BoolConstant< HasMutableDataAccess::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool SF > +struct IsAligned< Column > + : public BoolConstant< And< IsAligned, Or< IsColumnMajorMatrix, IsSymmetric > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool SF > +struct IsPadded< Column > + : public BoolConstant< And< IsPadded, Or< IsColumnMajorMatrix, IsSymmetric > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISOPPOSEDVIEW SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool DF > +struct IsOpposedView< Column > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ADDTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool SF, typename T > +struct AddTrait< Column, T > +{ + using Type = AddTrait_< ColumnTrait_, T >; +}; + +template< typename T, typename MT, bool SO, bool DF, bool SF > +struct AddTrait< T, Column > +{ + using Type = AddTrait_< T, ColumnTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool SF, typename T > +struct SubTrait< Column, T > +{ + using Type = SubTrait_< ColumnTrait_, T >; +}; + +template< typename T, typename MT, bool SO, bool DF, bool SF > +struct SubTrait< T, Column > +{ + using Type = SubTrait_< T, ColumnTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool SF, typename T > +struct MultTrait< Column, T > +{ + using Type = MultTrait_< ColumnTrait_, T >; +}; + +template< typename T, typename MT, bool SO, bool DF, bool SF > +struct MultTrait< T, Column > +{ + using Type = MultTrait_< T, ColumnTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// CROSSTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool SF, typename T > +struct CrossTrait< Column, T > +{ + using Type = CrossTrait_< ColumnTrait_, T >; +}; + +template< typename T, typename MT, bool SO, bool DF, bool SF > +struct CrossTrait< T, Column > +{ + using Type = CrossTrait_< T, ColumnTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool SF, typename T > +struct DivTrait< Column, T > +{ + using Type = DivTrait_< ColumnTrait_, T >; +}; + +template< typename T, typename MT, bool SO, bool DF, bool SF > +struct DivTrait< T, Column > +{ + using Type = DivTrait_< T, ColumnTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTORTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool SF > +struct SubvectorTrait< Column > +{ + using Type = SubvectorTrait_< ResultType_< Column > >; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 DenseMatrix; + typedef blaze::CompressedMatrix SparseMatrix; + + DenseMatrix D; + SparseMatrix S; + // ... Resizing and initialization + + // Creating a view on the 3rd row of the dense matrix D + blaze::Row = row( D, 3UL ); + + // Creating a view on the 4th row of the sparse matrix S + blaze::Row = row( S, 4UL ); + \endcode +*/ +template< typename MT // Type of the matrix + , bool SO > // Storage order +inline DisableIf_< Or< IsComputation, IsTransExpr >, RowExprTrait_ > + row( Matrix& matrix, size_t index ) +{ + BLAZE_FUNCTION_TRACE; + + return RowExprTrait_( ~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 DenseMatrix; + typedef blaze::CompressedMatrix SparseMatrix; + + DenseMatrix D; + SparseMatrix S; + // ... Resizing and initialization + + // Creating a view on the 3rd row of the dense matrix D + blaze::Row = row( D, 3UL ); + + // Creating a view on the 4th row of the sparse matrix S + blaze::Row = row( S, 4UL ); + \endcode +*/ +template< typename MT // Type of the matrix + , bool SO > // Storage order +inline DisableIf_< Or< IsComputation, IsTransExpr >, RowExprTrait_ > + row( const Matrix& matrix, size_t index ) +{ + BLAZE_FUNCTION_TRACE; + + return RowExprTrait_( ~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, RowExprTrait_ > + row( const Matrix& 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, RowExprTrait_ > + row( const Matrix& 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, RowExprTrait_ > + row( const Matrix& 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, RowExprTrait_ > + row( const Matrix& 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, RowExprTrait_ > + row( const Matrix& 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, RowExprTrait_ > + row( const Matrix& 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, RowExprTrait_ > + row( const Matrix& 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, RowExprTrait_ > + row( const Matrix& 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, RowExprTrait_ > + row( const Matrix& 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, RowExprTrait_ > + row( const Matrix& 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& row ); + +template< typename MT, bool SO, bool DF, bool SF > +inline void clear( Row& row ); + +template< typename MT, bool SO, bool DF, bool SF > +inline bool isDefault( const Row& row ); + +template< typename MT, bool SO, bool DF, bool SF > +inline bool isIntact( const Row& row ) noexcept; + +template< typename MT, bool SO, bool DF, bool SF > +inline bool isSame( const Row& a, const Row& 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& 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& 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 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& row ) +{ + for( size_t i=0UL; i 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& row ) +{ + typedef ConstIterator_< Row > 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 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& 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& a, const Row& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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 > derestrict( Row& row ) +{ + typedef DerestrictTrait_< Row > 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 > + : public BoolConstant< IsRestricted::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DERESTRICTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool SF > +struct DerestrictTrait< Row > +{ + using Type = Row< RemoveReference_< DerestrictTrait_ > >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool SF > +struct HasConstDataAccess< Row > + : public BoolConstant< HasConstDataAccess::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool SF > +struct HasMutableDataAccess< Row > + : public BoolConstant< HasMutableDataAccess::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool SF > +struct IsAligned< Row > + : public BoolConstant< And< IsAligned, Or< IsRowMajorMatrix, IsSymmetric > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISPADDED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool SF > +struct IsPadded< Row > + : public BoolConstant< And< IsPadded, Or< IsRowMajorMatrix, IsSymmetric > >::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISOPPOSEDVIEW SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool DF > +struct IsOpposedView< Row > + : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ADDTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool SF, typename T > +struct AddTrait< Row, T > +{ + using Type = AddTrait_< RowTrait_, T >; +}; + +template< typename T, typename MT, bool SO, bool DF, bool SF > +struct AddTrait< T, Row > +{ + using Type = AddTrait_< T, RowTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool SF, typename T > +struct SubTrait< Row, T > +{ + using Type = SubTrait_< RowTrait_, T >; +}; + +template< typename T, typename MT, bool SO, bool DF, bool SF > +struct SubTrait< T, Row > +{ + using Type = SubTrait_< T, RowTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool SF, typename T > +struct MultTrait< Row, T > +{ + using Type = MultTrait_< RowTrait_, T >; +}; + +template< typename T, typename MT, bool SO, bool DF, bool SF > +struct MultTrait< T, Row > +{ + using Type = MultTrait_< T, RowTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// CROSSTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool SF, typename T > +struct CrossTrait< Row, T > +{ + using Type = CrossTrait_< RowTrait_, T >; +}; + +template< typename T, typename MT, bool SO, bool DF, bool SF > +struct CrossTrait< T, Row > +{ + using Type = CrossTrait_< T, RowTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool SF, typename T > +struct DivTrait< Row, T > +{ + using Type = DivTrait_< RowTrait_, T >; +}; + +template< typename T, typename MT, bool SO, bool DF, bool SF > +struct DivTrait< T, Row > +{ + using Type = DivTrait_< T, RowTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTORTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO, bool DF, bool SF > +struct SubvectorTrait< Row > +{ + using Type = SubvectorTrait_< ResultType_< Row > >; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 DenseMatrix; + typedef blaze::CompressedMatrix SparseMatrix; + + DenseMatrix D; + SparseMatrix S; + // ... Resizing and initialization + + // Creating a dense submatrix of size 8x4, starting in row 0 and column 16 + blaze::Submatrix dsm = submatrix( D, 0UL, 16UL, 8UL, 4UL ); + + // Creating a sparse submatrix of size 7x3, starting in row 2 and column 4 + blaze::Submatrix 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 dsm = submatrix( D, 0UL, 16UL, 8UL, 4UL ); + blaze::Submatrix dsm = submatrix ( D, 0UL, 16UL, 8UL, 4UL ); + blaze::Submatrix dsm = submatrix( 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 dsm = submatrix( 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_ + submatrix( Matrix& matrix, size_t row, size_t column, size_t m, size_t n ) +{ + BLAZE_FUNCTION_TRACE; + + return submatrix( ~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 DenseMatrix; + typedef blaze::CompressedMatrix SparseMatrix; + + DenseMatrix D; + SparseMatrix S; + // ... Resizing and initialization + + // Creating a dense submatrix of size 8x4, starting in row 0 and column 16 + blaze::Submatrix dsm = submatrix( D, 0UL, 16UL, 8UL, 4UL ); + + // Creating a sparse submatrix of size 7x3, starting in row 2 and column 4 + blaze::Submatrix 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 dsm = submatrix( D, 0UL, 16UL, 8UL, 4UL ); + blaze::Submatrix dsm = submatrix ( D, 0UL, 16UL, 8UL, 4UL ); + blaze::Submatrix dsm = submatrix( 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 dsm = submatrix( 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_ + submatrix( const Matrix& matrix, size_t row, size_t column, size_t m, size_t n ) +{ + BLAZE_FUNCTION_TRACE; + + return submatrix( ~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 DenseMatrix; + typedef blaze::CompressedMatrix 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 dsm = submatrix( D, 0UL, 16UL, 8UL, 4UL ); + + // Creating an unaligned sparse submatrix of size 7x3, starting in row 2 and column 4 + blaze::Submatrix 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. +// +// 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 MatrixType; + typedef blaze::Submatrix 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( 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( 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( 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( 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, IsTransExpr >, SubmatrixExprTrait_ > + submatrix( Matrix& matrix, size_t row, size_t column, size_t m, size_t n ) +{ + BLAZE_FUNCTION_TRACE; + + return SubmatrixExprTrait_( ~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 DenseMatrix; + typedef blaze::CompressedMatrix 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 dsm = submatrix( D, 0UL, 16UL, 8UL, 4UL ); + + // Creating an unaligned sparse submatrix of size 7x3, starting in row 2 and column 4 + blaze::Submatrix 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. +// +// 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 MatrixType; + typedef blaze::Submatrix 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( 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( 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( 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( 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, IsTransExpr >, SubmatrixExprTrait_ > + submatrix( const Matrix& matrix, size_t row, size_t column, size_t m, size_t n ) +{ + BLAZE_FUNCTION_TRACE; + + return SubmatrixExprTrait_( ~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, SubvectorExprTrait_ > + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + typedef RemoveReference_< LeftOperand_ > MT; + + LeftOperand_ left ( (~vector).leftOperand() ); + RightOperand_ right( (~vector).rightOperand() ); + + const size_t column( ( IsUpper::value ) + ?( ( !AF && IsStrictlyUpper::value )?( index + 1UL ):( index ) ) + :( 0UL ) ); + const size_t n( ( IsLower::value ) + ?( ( IsUpper::value )?( size ) + :( ( IsStrictlyLower::value && size > 0UL ) + ?( index + size - 1UL ) + :( index + size ) ) ) + :( ( IsUpper::value )?( left.columns() - column ) + :( left.columns() ) ) ); + + return submatrix( left, index, column, size, n ) * subvector( 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, SubvectorExprTrait_ > + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + typedef RemoveReference_< RightOperand_ > MT; + + LeftOperand_ left ( (~vector).leftOperand() ); + RightOperand_ right( (~vector).rightOperand() ); + + const size_t row( ( IsLower::value ) + ?( ( !AF && IsStrictlyLower::value )?( index + 1UL ):( index ) ) + :( 0UL ) ); + const size_t m( ( IsUpper::value ) + ?( ( IsLower::value )?( size ) + :( ( IsStrictlyUpper::value && size > 0UL ) + ?( index + size - 1UL ) + :( index + size ) ) ) + :( ( IsLower::value )?( right.rows() - row ) + :( right.rows() ) ) ); + + return subvector( left, row, m ) * submatrix( 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, SubmatrixExprTrait_ > + submatrix( const Matrix& matrix, size_t row, size_t column, size_t m, size_t n ) +{ + BLAZE_FUNCTION_TRACE; + + return submatrix( (~matrix).leftOperand() , row, column, m, n ) + + submatrix( (~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, SubmatrixExprTrait_ > + submatrix( const Matrix& matrix, size_t row, size_t column, size_t m, size_t n ) +{ + BLAZE_FUNCTION_TRACE; + + return submatrix( (~matrix).leftOperand() , row, column, m, n ) - + submatrix( (~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, SubmatrixExprTrait_ > + submatrix( const Matrix& matrix, size_t row, size_t column, size_t m, size_t n ) +{ + BLAZE_FUNCTION_TRACE; + + typedef RemoveReference_< LeftOperand_ > MT1; + typedef RemoveReference_< RightOperand_ > MT2; + + LeftOperand_ left ( (~matrix).leftOperand() ); + RightOperand_ right( (~matrix).rightOperand() ); + + const size_t begin( max( ( IsUpper::value ) + ?( ( !AF && IsStrictlyUpper::value )?( row + 1UL ):( row ) ) + :( 0UL ) + , ( IsLower::value ) + ?( ( !AF && IsStrictlyLower::value )?( column + 1UL ):( column ) ) + :( 0UL ) ) ); + const size_t end( min( ( IsLower::value ) + ?( ( IsStrictlyLower::value && m > 0UL )?( row + m - 1UL ):( row + m ) ) + :( left.columns() ) + , ( IsUpper::value ) + ?( ( IsStrictlyUpper::value && n > 0UL )?( column + n - 1UL ):( column + n ) ) + :( left.columns() ) ) ); + + const size_t diff( ( begin < end )?( end - begin ):( 0UL ) ); + + return submatrix( left, row, begin, m, diff ) * + submatrix( 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, SubmatrixExprTrait_ > + submatrix( const Matrix& matrix, size_t row, size_t column, size_t m, size_t n ) +{ + BLAZE_FUNCTION_TRACE; + + return subvector( (~matrix).leftOperand(), row, m ) * + subvector( (~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, SubmatrixExprTrait_ > + submatrix( const Matrix& matrix, size_t row, size_t column, size_t m, size_t n ) +{ + BLAZE_FUNCTION_TRACE; + + return submatrix( (~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, SubmatrixExprTrait_ > + submatrix( const Matrix& matrix, size_t row, size_t column, size_t m, size_t n ) +{ + BLAZE_FUNCTION_TRACE; + + return submatrix( (~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, SubmatrixExprTrait_ > + submatrix( const Matrix& matrix, size_t row, size_t column, size_t m, size_t n ) +{ + BLAZE_FUNCTION_TRACE; + + return forEach( submatrix( (~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, SubmatrixExprTrait_ > + submatrix( const Matrix& matrix, size_t row, size_t column, size_t m, size_t n ) +{ + BLAZE_FUNCTION_TRACE; + + return eval( submatrix( (~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, SubmatrixExprTrait_ > + submatrix( const Matrix& matrix, size_t row, size_t column, size_t m, size_t n ) +{ + BLAZE_FUNCTION_TRACE; + + return serial( submatrix( (~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, SubmatrixExprTrait_ > + submatrix( const Matrix& matrix, size_t row, size_t column, size_t m, size_t n ) +{ + BLAZE_FUNCTION_TRACE; + + return trans( submatrix( (~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 + submatrix( const Submatrix& 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( 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& sm ); + +template< typename MT, bool AF, bool SO, bool DF > +inline void reset( Submatrix& sm, size_t i ); + +template< typename MT, bool AF, bool SO, bool DF > +inline void clear( Submatrix& sm ); + +template< typename MT, bool AF, bool SO, bool DF > +inline bool isDefault( const Submatrix& sm ); + +template< typename MT, bool AF, bool SO, bool DF > +inline bool isIntact( const Submatrix& sm ) noexcept; + +template< typename MT, bool AF, bool SO, bool DF > +inline bool isSymmetric( const Submatrix& sm ); + +template< typename MT, bool AF, bool SO, bool DF > +inline bool isHermitian( const Submatrix& sm ); + +template< typename MT, bool AF, bool SO, bool DF > +inline bool isLower( const Submatrix& sm ); + +template< typename MT, bool AF, bool SO, bool DF > +inline bool isUniLower( const Submatrix& sm ); + +template< typename MT, bool AF, bool SO, bool DF > +inline bool isStrictlyLower( const Submatrix& sm ); + +template< typename MT, bool AF, bool SO, bool DF > +inline bool isUpper( const Submatrix& sm ); + +template< typename MT, bool AF, bool SO, bool DF > +inline bool isUniUpper( const Submatrix& sm ); + +template< typename MT, bool AF, bool SO, bool DF > +inline bool isStrictlyUpper( const Submatrix& sm ); + +template< typename MT, bool AF, bool SO, bool DF > +inline bool isSame( const Submatrix& a, const Matrix& b ) noexcept; + +template< typename MT, bool AF, bool SO, bool DF > +inline bool isSame( const Matrix& a, const Submatrix& b ) noexcept; + +template< typename MT, bool AF, bool SO, bool DF > +inline bool isSame( const Submatrix& a, const Submatrix& 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& 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& 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& 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 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& 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 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& sm ) +{ + using blaze::isDefault; + + typedef ConstIterator_< Submatrix > ConstIterator; + + const size_t iend( ( SO == rowMajor)?( sm.rows() ):( sm.columns() ) ); + + for( size_t i=0UL; ivalue() ) ) 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 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& 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 Matrix; + + Matrix A( 32UL, 16UL ); + // ... Initialization + + blaze::Submatrix 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& sm ) +{ + using BaseType = BaseType_< Submatrix >; + + if( IsSymmetric::value && sm.row() == sm.column() && sm.rows() == sm.columns() ) + return true; + else return isSymmetric( static_cast( 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 Matrix; + + Matrix A( 32UL, 16UL ); + // ... Initialization + + blaze::Submatrix 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& sm ) +{ + using BaseType = BaseType_< Submatrix >; + + if( IsHermitian::value && sm.row() == sm.column() && sm.rows() == sm.columns() ) + return true; + else return isHermitian( static_cast( 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 Matrix; + + Matrix A( 32UL, 16UL ); + // ... Initialization + + blaze::Submatrix 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& sm ) +{ + using BaseType = BaseType_< Submatrix >; + + if( IsLower::value && sm.row() == sm.column() && sm.rows() == sm.columns() ) + return true; + else return isLower( static_cast( 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 Matrix; + + Matrix A( 32UL, 16UL ); + // ... Initialization + + blaze::Submatrix 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& sm ) +{ + using BaseType = BaseType_< Submatrix >; + + if( IsUniLower::value && sm.row() == sm.column() && sm.rows() == sm.columns() ) + return true; + else return isUniLower( static_cast( 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 Matrix; + + Matrix A( 32UL, 16UL ); + // ... Initialization + + blaze::Submatrix 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& sm ) +{ + using BaseType = BaseType_< Submatrix >; + + if( IsStrictlyLower::value && sm.row() == sm.column() && sm.rows() == sm.columns() ) + return true; + else return isStrictlyLower( static_cast( 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 Matrix; + + Matrix A( 32UL, 16UL ); + // ... Initialization + + blaze::Submatrix 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& sm ) +{ + using BaseType = BaseType_< Submatrix >; + + if( IsUpper::value && sm.row() == sm.column() && sm.rows() == sm.columns() ) + return true; + else return isUpper( static_cast( 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 Matrix; + + Matrix A( 32UL, 16UL ); + // ... Initialization + + blaze::Submatrix 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& sm ) +{ + using BaseType = BaseType_< Submatrix >; + + if( IsUniUpper::value && sm.row() == sm.column() && sm.rows() == sm.columns() ) + return true; + else return isUniUpper( static_cast( 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 Matrix; + + Matrix A( 32UL, 16UL ); + // ... Initialization + + blaze::Submatrix 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& sm ) +{ + using BaseType = BaseType_< Submatrix >; + + if( IsStrictlyUpper::value && sm.row() == sm.column() && sm.rows() == sm.columns() ) + return true; + else return isStrictlyUpper( static_cast( 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& a, const Matrix& 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& a, const Submatrix& 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& a, const Submatrix& 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( A ); // Inversion of a general matrix + invert( A ); // Inversion of a symmetric indefinite matrix + invert( A ); // Inversion of a Hermitian indefinite matrix + invert( 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 > invert( Submatrix& sm ) +{ + typedef ResultType_< Submatrix > RT; + + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION ( RT ); + BLAZE_CONSTRAINT_MUST_HAVE_MUTABLE_DATA_ACCESS( RT ); + + RT tmp( sm ); + invert( 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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 > derestrict( Submatrix& dm ) +{ + typedef DerestrictTrait_< Submatrix > 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 > + : public BoolConstant< IsRestricted::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DERESTRICTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool AF, bool SO, bool DF > +struct DerestrictTrait< Submatrix > +{ + using Type = Submatrix< RemoveReference_< DerestrictTrait_ >, AF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool AF, bool SO > +struct HasConstDataAccess< Submatrix > + : public BoolConstant< HasConstDataAccess::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool AF, bool SO > +struct HasMutableDataAccess< Submatrix > + : public BoolConstant< HasMutableDataAccess::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool SO > +struct IsAligned< Submatrix > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ADDTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool AF, bool SO, bool DF, typename T > +struct AddTrait< Submatrix, T > +{ + using Type = AddTrait_< SubmatrixTrait_, T >; +}; + +template< typename T, typename MT, bool AF, bool SO, bool DF > +struct AddTrait< T, Submatrix > +{ + using Type = AddTrait_< T, SubmatrixTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool AF, bool SO, bool DF, typename T > +struct SubTrait< Submatrix, T > +{ + using Type = SubTrait_< SubmatrixTrait_, T >; +}; + +template< typename T, typename MT, bool AF, bool SO, bool DF > +struct SubTrait< T, Submatrix > +{ + using Type = SubTrait_< T, SubmatrixTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool AF, bool SO, bool DF, typename T > +struct MultTrait< Submatrix, T > +{ + using Type = MultTrait_< SubmatrixTrait_, T >; +}; + +template< typename T, typename MT, bool AF, bool SO, bool DF > +struct MultTrait< T, Submatrix > +{ + using Type = MultTrait_< T, SubmatrixTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool AF, bool SO, bool DF, typename T > +struct DivTrait< Submatrix, T > +{ + using Type = DivTrait_< SubmatrixTrait_, T >; +}; + +template< typename T, typename MT, bool AF, bool DF, bool SO > +struct DivTrait< T, Submatrix > +{ + using Type = DivTrait_< T, SubmatrixTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool AF, bool SO, bool DF > +struct SubmatrixTrait< Submatrix > +{ + using Type = SubmatrixTrait_< ResultType_< Submatrix > >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBMATRIXEXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool AF1, bool SO, bool DF, bool AF2 > +struct SubmatrixExprTrait< Submatrix, AF2 > +{ + using Type = Submatrix; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool AF1, bool SO, bool DF, bool AF2 > +struct SubmatrixExprTrait< const Submatrix, AF2 > +{ + using Type = Submatrix; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool AF1, bool SO, bool DF, bool AF2 > +struct SubmatrixExprTrait< volatile Submatrix, AF2 > +{ + using Type = Submatrix; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool AF1, bool SO, bool DF, bool AF2 > +struct SubmatrixExprTrait< const volatile Submatrix, AF2 > +{ + using Type = Submatrix; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ROWTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool AF, bool SO, bool DF > +struct RowTrait< Submatrix > +{ + using Type = RowTrait_< ResultType_< Submatrix > >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// COLUMNTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename MT, bool AF, bool SO, bool DF > +struct ColumnTrait< Submatrix > +{ + using Type = ColumnTrait_< ResultType_< Submatrix > >; +}; +/*! \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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 DenseVector; + typedef blaze::CompressedVector SparseVector; + + DenseVector d; + SparseVector s; + // ... Resizing and initialization + + // Creating a dense subvector of size 8, starting from index 4 + blaze::Subvector dsv = subvector( d, 4UL, 8UL ); + + // Creating a sparse subvector of size 7, starting from index 5 + blaze::Subvector 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 dsv = subvector( v, 4UL, 8UL ); + blaze::Subvector dsv = subvector ( v, 4UL, 8UL ); + blaze::Subvector dsv = subvector( 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 = subvector( 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_ + subvector( Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return subvector( ~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 DenseVector; + typedef blaze::CompressedVector SparseVector; + + DenseVector d; + SparseVector s; + // ... Resizing and initialization + + // Creating a dense subvector of size 8, starting from index 4 + blaze::Subvector dsv = subvector( d, 4UL, 8UL ); + + // Creating a sparse subvector of size 7, starting from index 5 + blaze::Subvector 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 dsv = subvector( v, 4UL, 8UL ); + blaze::Subvector dsv = subvector ( v, 4UL, 8UL ); + blaze::Subvector dsv = subvector( 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 = subvector( 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_ + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return subvector( ~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 DenseVector; + typedef blaze::CompressedVector SparseVector; + + DenseVector d; + SparseVector s; + // ... Resizing and initialization + + // Creating an aligned dense subvector of size 8 starting from index 4 + blaze::Subvector dsv = subvector( d, 4UL, 8UL ); + + // Creating an unaligned subvector of size 7 starting from index 3 + blaze::Subvector ssv = subvector( 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 VectorType; + typedef blaze::Subvector SubvectorType; + + VectorType d( 17UL ); + // ... Resizing and initialization + + // OK: Starts at the beginning, i.e. the first element is aligned + SubvectorType dsv1 = subvector( d, 0UL, 13UL ); + + // OK: Start index is a multiple of 4, i.e. the first element is aligned + SubvectorType dsv2 = subvector( d, 4UL, 7UL ); + + // OK: The start index is a multiple of 4 and the subvector includes the last element + SubvectorType dsv3 = subvector( d, 8UL, 9UL ); + + // Error: Start index is not a multiple of 4, i.e. the first element is not aligned + SubvectorType dsv4 = subvector( 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, IsTransExpr >, SubvectorExprTrait_ > + subvector( Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return SubvectorExprTrait_( ~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 DenseVector; + typedef blaze::CompressedVector SparseVector; + + DenseVector d; + SparseVector s; + // ... Resizing and initialization + + // Creating an aligned dense subvector of size 8 starting from index 4 + blaze::Subvector dsv = subvector( d, 4UL, 8UL ); + + // Creating an unaligned subvector of size 7 starting from index 3 + blaze::Subvector ssv = subvector( 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 VectorType; + typedef blaze::Subvector SubvectorType; + + VectorType d( 17UL ); + // ... Resizing and initialization + + // OK: Starts at the beginning, i.e. the first element is aligned + SubvectorType dsv1 = subvector( d, 0UL, 13UL ); + + // OK: Start index is a multiple of 4, i.e. the first element is aligned + SubvectorType dsv2 = subvector( d, 4UL, 7UL ); + + // OK: The start index is a multiple of 4 and the subvector includes the last element + SubvectorType dsv3 = subvector( d, 8UL, 9UL ); + + // Error: Start index is not a multiple of 4, i.e. the first element is not aligned + SubvectorType dsv4 = subvector( 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, IsTransExpr >, SubvectorExprTrait_ > + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return SubvectorExprTrait_( ~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, SubvectorExprTrait_ > + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return subvector( (~vector).leftOperand() , index, size ) + + subvector( (~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, SubvectorExprTrait_ > + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return subvector( (~vector).leftOperand() , index, size ) - + subvector( (~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, SubvectorExprTrait_ > + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return subvector( (~vector).leftOperand() , index, size ) * + subvector( (~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, SubvectorExprTrait_ > + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return subvector( (~vector).leftOperand() , index, size ) / + subvector( (~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, SubvectorExprTrait_ > + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return SubvectorExprTrait_( ~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, SubvectorExprTrait_ > + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return subvector( (~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, SubvectorExprTrait_ > + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return subvector( (~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, SubvectorExprTrait_ > + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return forEach( subvector( (~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, SubvectorExprTrait_ > + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return eval( subvector( (~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, SubvectorExprTrait_ > + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return serial( subvector( (~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, SubvectorExprTrait_ > + subvector( const Vector& vector, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + return trans( subvector( (~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 + subvector( const Subvector& sv, size_t index, size_t size ) +{ + BLAZE_FUNCTION_TRACE; + + if( index + size > sv.size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid subvector specification" ); + } + + return Subvector( 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& sv ); + +template< typename VT, bool AF, bool TF, bool DF > +inline void clear( Subvector& sv ); + +template< typename VT, bool AF, bool TF, bool DF > +inline bool isDefault( const Subvector& sv ); + +template< typename VT, bool AF, bool TF, bool DF > +inline bool isIntact( const Subvector& sv ) noexcept; + +template< typename VT, bool AF, bool TF, bool DF > +inline bool isSame( const Subvector& a, const Vector& b ) noexcept; + +template< typename VT, bool AF, bool TF, bool DF > +inline bool isSame( const Vector& a, const Subvector& b ) noexcept; + +template< typename VT, bool AF, bool TF, bool DF > +inline bool isSame( const Subvector& a, const Subvector& 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& 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& 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 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& sv ) +{ + for( size_t i=0UL; i 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& sv ) +{ + typedef ConstIterator_< Subvector > 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 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& 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& a, const Vector& 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& a, const Subvector& 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& a, const Subvector& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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& lhs, const Vector& 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 > derestrict( Subvector& sv ) +{ + typedef DerestrictTrait_< Subvector > 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 > + : public BoolConstant< IsRestricted::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DERESTRICTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool AF, bool TF, bool DF > +struct DerestrictTrait< Subvector > +{ + using Type = Subvector< RemoveReference_< DerestrictTrait_ >, AF, TF, DF >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASCONSTDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool AF, bool TF > +struct HasConstDataAccess< Subvector > + : public BoolConstant< HasConstDataAccess::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// HASMUTABLEDATAACCESS SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool AF, bool TF > +struct HasMutableDataAccess< Subvector > + : public BoolConstant< HasMutableDataAccess::value > +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ISALIGNED SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool TF > +struct IsAligned< Subvector > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// ADDTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool AF, bool TF, bool DF, typename T > +struct AddTrait< Subvector, T > +{ + using Type = AddTrait_< SubvectorTrait_, T >; +}; + +template< typename T, typename VT, bool AF, bool TF, bool DF > +struct AddTrait< T, Subvector > +{ + using Type = AddTrait_< T, SubvectorTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool AF, bool TF, bool DF, typename T > +struct SubTrait< Subvector, T > +{ + using Type = SubTrait_< SubvectorTrait_, T >; +}; + +template< typename T, typename VT, bool AF, bool TF, bool DF > +struct SubTrait< T, Subvector > +{ + using Type = SubTrait_< T, SubvectorTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// MULTTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool AF, bool TF, bool DF, typename T > +struct MultTrait< Subvector, T > +{ + using Type = MultTrait_< SubvectorTrait_, T >; +}; + +template< typename T, typename VT, bool AF, bool TF, bool DF > +struct MultTrait< T, Subvector > +{ + using Type = MultTrait_< T, SubvectorTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// CROSSTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool AF, bool TF, bool DF, typename T > +struct CrossTrait< Subvector, T > +{ + using Type = CrossTrait_< SubvectorTrait_, T >; +}; + +template< typename T, typename VT, bool AF, bool TF, bool DF > +struct CrossTrait< T, Subvector > +{ + using Type = CrossTrait_< T, SubvectorTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// DIVTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool AF, bool TF, bool DF, typename T > +struct DivTrait< Subvector, T > +{ + using Type = DivTrait_< SubvectorTrait_, T >; +}; + +template< typename T, typename VT, bool AF, bool TF, bool DF > +struct DivTrait< T, Subvector > +{ + using Type = DivTrait_< T, SubvectorTrait_ >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTORTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool AF, bool TF, bool DF > +struct SubvectorTrait< Subvector > +{ + using Type = SubvectorTrait_< ResultType_< Subvector > >; +}; +/*! \endcond */ +//************************************************************************************************* + + + + +//================================================================================================= +// +// SUBVECTOREXPRTRAIT SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool AF1, bool TF, bool DF, bool AF2 > +struct SubvectorExprTrait< Subvector, AF2 > +{ + using Type = Subvector; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool AF1, bool TF, bool DF, bool AF2 > +struct SubvectorExprTrait< const Subvector, AF2 > +{ + using Type = Subvector; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool AF1, bool TF, bool DF, bool AF2 > +struct SubvectorExprTrait< volatile Subvector, AF2 > +{ + using Type = Subvector; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT, bool AF1, bool TF, bool DF, bool AF2 > +struct SubvectorExprTrait< const volatile Subvector, AF2 > +{ + using Type = Subvector; +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< DVecDVecCrossExpr, AF > +{ + public: + //********************************************************************************************** + using Type = Subvector< DVecDVecCrossExpr, unaligned, TF, true >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< DVecSVecCrossExpr, AF > +{ + public: + //********************************************************************************************** + using Type = Subvector< DVecSVecCrossExpr, unaligned, TF, true >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< SVecDVecCrossExpr, AF > +{ + public: + //********************************************************************************************** + using Type = Subvector< SVecDVecCrossExpr, unaligned, TF, true >; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +template< typename VT1, typename VT2, bool TF, bool AF > +struct SubvectorExprTrait< SVecSVecCrossExpr, AF > +{ + public: + //********************************************************************************************** + using Type = Subvector< SVecSVecCrossExpr, 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 +#include +#include +#include + + +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; + using SparseVectorType = blaze::CompressedVector; + using DenseMatrixType = blaze::DynamicMatrix; + using SparseMatrixType = blaze::CompressedMatrix; + + DenseVectorType x; + SparseVectorType y; + DenseMatrixType A, B; + SparseMatrixType C, D; + // ... Resizing and initialization + + // Setting the 1st column of matrix A to x + blaze::Column 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; + MatrixType A; + // ... Resizing and initialization + + // Creating a view on the 4th column of matrix A + blaze::Column 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; + using ColumnType = blaze::Column; + + 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; + using ColumnType = blaze::Column; + + 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; + MatrixType A( 100UL, 10UL ); // Non-initialized 100x10 matrix + + using ColumnType = blaze::Column; + 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; + using ColumnType = blaze::Column; + + 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 a( 2UL, 2.0 ), b; + blaze::CompressedVector c( 2UL ); + c[1] = 3.0; + + using MatrixType = blaze::DynamicMatrix; + MatrixType A( 2UL, 4UL ); // Non-initialized 2x4 matrix + + using ColumnType = blaze::Column; + 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; + using ColumnType = blaze::Column; + + 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 A( 128UL, 128UL ); + blaze::DynamicMatrix B( 128UL, 128UL ); + // ... Resizing and initialization + + // The computation of the 15th column of the multiplication between A and B ... + blaze::DynamicVector 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 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::value // Storage order + , bool DF = IsDenseMatrix::value // Density flag + , bool SF = IsSymmetric::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public DenseVector< Column, false > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Column This; //!< Type of this Column instance. + typedef DenseVector BaseType; //!< Base type of this Column instance. + typedef ColumnTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the column elements. + typedef SIMDTrait_ SIMDType; //!< SIMD type of the column elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant column value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Pointer to a constant column value. + typedef const ElementType* ConstPointer; + + //! Pointer to a non-constant column value. + typedef If_< Or< IsConst, Not< HasMutableDataAccess > >, ConstPointer, ElementType* > Pointer; + + //! Iterator over constant elements. + typedef ConstIterator_ ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, Iterator_ > 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 list ); + inline Column& operator=( const Column& rhs ); + + template< typename VT > inline Column& operator= ( const Vector& rhs ); + template< typename VT > inline Column& operator+=( const Vector& rhs ); + template< typename VT > inline Column& operator-=( const Vector& rhs ); + template< typename VT > inline Column& operator*=( const DenseVector& rhs ); + template< typename VT > inline Column& operator*=( const SparseVector& rhs ); + template< typename VT > inline Column& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, Column >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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_ >::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_ >::value && + HasSIMDAdd< ElementType, ElementType_ >::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_ >::value && + HasSIMDSub< ElementType, ElementType_ >::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_ >::value && + HasSIMDMult< ElementType, ElementType_ >::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_ >::value && + HasSIMDDiv< ElementType, ElementType_ >::value }; + }; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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* 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* 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 > assign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedAssign > assign( const DenseVector& rhs ); + + template< typename VT > inline void assign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedAddAssign > addAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedAddAssign > addAssign( const DenseVector& rhs ); + + template< typename VT > inline void addAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedSubAssign > subAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedSubAssign > subAssign( const DenseVector& rhs ); + + template< typename VT > inline void subAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedMultAssign > multAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedMultAssign > multAssign( const DenseVector& rhs ); + + template< typename VT > inline void multAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedDivAssign > divAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedDivAssign > divAssign( const DenseVector& 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& column ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend bool isSame( const Column& a, const Column& b ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAddAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool trySubAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryMultAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryDivAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend DerestrictTrait_< Column > derestrict( Column& 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::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::Reference Column::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::ConstReference + Column::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid column access index" ); + return const_cast( 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::Reference Column::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::ConstReference + Column::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::Pointer Column::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::ConstPointer Column::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::Iterator Column::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::ConstIterator Column::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::ConstIterator Column::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::Iterator Column::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::ConstIterator Column::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::ConstIterator Column::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& Column::operator=( const ElementType& rhs ) +{ + const size_t ibegin( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( col_+1UL ) + :( col_ ) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( col_ ) + :( col_+1UL ) ) + :( size() ) ); + + for( size_t i=ibegin; i // Symmetry flag +inline Column& Column::operator=( initializer_list 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& Column::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_ 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& Column::operator=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ tmp( right ); + smpAssign( left, tmp ); + } + else { + if( IsSparseVector::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& Column::operator+=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAddAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Column::operator-=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !trySubAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Column::operator*=( const DenseVector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryMultAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Column::operator*=( const SparseVector& 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_ 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& Column::operator/=( const DenseVector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryDivAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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, Column >& + Column::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, Column >& + Column::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::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::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::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::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& Column::scale( const Other& scalar ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( col_+1UL ) + :( col_ ) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( col_ ) + :( col_+1UL ) ) + :( size() ) ); + + for( size_t i=ibegin; i // Symmetry flag +template< typename Other > // Data type of the foreign expression +inline bool Column::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::canAlias( const Column* 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::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::isAliased( const Column* 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::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::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::SIMDType + Column::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::SIMDType + Column::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::SIMDType + Column::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::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::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::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::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::BLAZE_TEMPLATE VectorizedAssign > + Column::assign( const DenseVector& 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 // Symmetry flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Column::BLAZE_TEMPLATE VectorizedAssign > + Column::assign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ right( (~rhs).begin() ); + + if( useStreaming && rows > ( cacheSize/( sizeof(ElementType) * 3UL ) ) && !(~rhs).isAliased( this ) ) + { + for( ; i // Symmetry flag +template< typename VT > // Type of the right-hand side sparse vector +inline void Column::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedAddAssign > + Column::addAssign( const DenseVector& 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 // Symmetry flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Column::BLAZE_TEMPLATE VectorizedAddAssign > + Column::addAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ 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 // Symmetry flag +template< typename VT > // Type of the right-hand side sparse vector +inline void Column::addAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedSubAssign > + Column::subAssign( const DenseVector& 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 // Symmetry flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Column::BLAZE_TEMPLATE VectorizedSubAssign > + Column::subAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ 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 // Symmetry flag +template< typename VT > // Type of the right-hand side sparse vector +inline void Column::subAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedMultAssign > + Column::multAssign( const DenseVector& 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 // Symmetry flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Column::BLAZE_TEMPLATE VectorizedMultAssign > + Column::multAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ 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 // Symmetry flag +template< typename VT > // Type of the right-hand side sparse vector +inline void Column::multAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const ResultType tmp( serial( *this ) ); + + reset(); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedDivAssign > + Column::divAssign( const DenseVector& 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 // Symmetry flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Column::BLAZE_TEMPLATE VectorizedDivAssign > + Column::divAssign( const DenseVector& 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_ 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 // Type of the dense matrix +class Column + : public DenseVector< Column, false > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Column This; //!< Type of this Column instance. + typedef DenseVector BaseType; //!< Base type of this Column instance. + typedef ColumnTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the column elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant column value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Pointer to a constant column value. + typedef const ElementType* ConstPointer; + + //! Pointer to a non-constant column value. + typedef If_< Or< IsConst, Not< HasMutableDataAccess > >, 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, ConstReference_, Reference_ > Reference; + + typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category. + typedef RemoveReference_ 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& 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& 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& 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& 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& 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& 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& 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 ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, ColumnIterator > 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 list ); + inline Column& operator=( const Column& rhs ); + + template< typename VT > inline Column& operator= ( const Vector& rhs ); + template< typename VT > inline Column& operator+=( const Vector& rhs ); + template< typename VT > inline Column& operator-=( const Vector& rhs ); + template< typename VT > inline Column& operator*=( const DenseVector& rhs ); + template< typename VT > inline Column& operator*=( const SparseVector& rhs ); + template< typename VT > inline Column& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, Column >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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* 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* alias ) const noexcept; + + inline bool isAligned () const noexcept; + inline bool canSMPAssign() const noexcept; + + template< typename VT > inline void assign ( const DenseVector & rhs ); + template< typename VT > inline void assign ( const SparseVector& rhs ); + template< typename VT > inline void addAssign ( const DenseVector & rhs ); + template< typename VT > inline void addAssign ( const SparseVector& rhs ); + template< typename VT > inline void subAssign ( const DenseVector & rhs ); + template< typename VT > inline void subAssign ( const SparseVector& rhs ); + template< typename VT > inline void multAssign( const DenseVector & rhs ); + template< typename VT > inline void multAssign( const SparseVector& rhs ); + template< typename VT > inline void divAssign ( const DenseVector & 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& column ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend bool isSame( const Column& a, const Column& b ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAddAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool trySubAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryMultAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryDivAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend DerestrictTrait_< Column > derestrict( Column& 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::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::Reference + Column::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::ConstReference + Column::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid column access index" ); + return const_cast( 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::Reference + Column::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::ConstReference + Column::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::Pointer Column::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::ConstPointer Column::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::Iterator Column::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::ConstIterator + Column::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::ConstIterator + Column::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::Iterator Column::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::ConstIterator + Column::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::ConstIterator + Column::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& + Column::operator=( const ElementType& rhs ) +{ + const size_t ibegin( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( col_+1UL ) + :( col_ ) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( col_ ) + :( col_+1UL ) ) + :( size() ) ); + + for( size_t i=ibegin; i // Type of the dense matrix +inline Column& + Column::operator=( initializer_list 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& + Column::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_ 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& + Column::operator=( const Vector& 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType tmp( right ); + smpAssign( left, tmp ); + } + else { + if( IsSparseVector::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& + Column::operator+=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAddAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& + Column::operator-=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !trySubAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& + Column::operator*=( const DenseVector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryMultAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& + Column::operator*=( const SparseVector& 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_ 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& + Column::operator/=( const DenseVector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryDivAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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, Column >& + Column::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, Column >& + Column::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::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::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::nonZeros() const +{ + const size_t rows( size() ); + size_t nonzeros( 0UL ); + + for( size_t i=0UL; i // Type of the dense matrix +inline void Column::reset() +{ + using blaze::clear; + + const size_t ibegin( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( col_+1UL ) + :( col_ ) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( col_ ) + :( col_+1UL ) ) + :( size() ) ); + + for( size_t i=ibegin; i // Type of the dense matrix +template< typename Other > // Data type of the scalar value +inline Column& Column::scale( const Other& scalar ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( col_+1UL ) + :( col_ ) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( col_ ) + :( col_+1UL ) ) + :( size() ) ); + + for( size_t i=ibegin; i // Type of the dense matrix +template< typename Other > // Data type of the foreign expression +inline bool Column::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::canAlias( const Column* 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::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::isAliased( const Column* 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::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::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::assign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Column::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::addAssign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Column::addAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::subAssign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Column::subAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::multAssign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Column::multAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const ResultType tmp( serial( *this ) ); + + reset(); + + for( ConstIterator_ 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::divAssign( const DenseVector& 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 // Type of the dense matrix +class Column + : public DenseVector< Column, false > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Column This; //!< Type of this Column instance. + typedef DenseVector BaseType; //!< Base type of this Column instance. + typedef ColumnTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the column elements. + typedef SIMDTrait_ SIMDType; //!< SIMD type of the column elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant column value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Pointer to a constant column value. + typedef const ElementType* ConstPointer; + + //! Pointer to a non-constant column value. + typedef If_< Or< IsConst, Not< HasMutableDataAccess > >, ConstPointer, ElementType* > Pointer; + + //! Iterator over constant elements. + typedef ConstIterator_ ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, Iterator_ > 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 list ); + inline Column& operator=( const Column& rhs ); + + template< typename VT > inline Column& operator= ( const Vector& rhs ); + template< typename VT > inline Column& operator+=( const Vector& rhs ); + template< typename VT > inline Column& operator-=( const Vector& rhs ); + template< typename VT > inline Column& operator*=( const DenseVector& rhs ); + template< typename VT > inline Column& operator*=( const SparseVector& rhs ); + template< typename VT > inline Column& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, Column >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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_ >::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_ >::value && + HasSIMDAdd< ElementType, ElementType_ >::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_ >::value && + HasSIMDSub< ElementType, ElementType_ >::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_ >::value && + HasSIMDMult< ElementType, ElementType_ >::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_ >::value && + HasSIMDDiv< ElementType, ElementType_ >::value }; + }; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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* 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* 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 > assign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedAssign > assign( const DenseVector& rhs ); + + template< typename VT > inline void assign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedAddAssign > addAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedAddAssign > addAssign( const DenseVector& rhs ); + + template< typename VT > inline void addAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedSubAssign > subAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedSubAssign > subAssign( const DenseVector& rhs ); + + template< typename VT > inline void subAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedMultAssign > multAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedMultAssign > multAssign( const DenseVector& rhs ); + + template< typename VT > inline void multAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedDivAssign > divAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedDivAssign > divAssign( const DenseVector& 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& column ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend bool isSame( const Column& a, const Column& b ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAddAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool trySubAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryMultAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryDivAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend DerestrictTrait_< Column > derestrict( Column& 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::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::Reference + Column::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::ConstReference + Column::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid column access index" ); + return const_cast( 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::Reference + Column::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::ConstReference + Column::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::Pointer Column::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::ConstPointer + Column::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::Iterator Column::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::ConstIterator Column::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::ConstIterator Column::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::Iterator Column::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::ConstIterator Column::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::ConstIterator Column::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& Column::operator=( const ElementType& rhs ) +{ + const size_t jbegin( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( col_+1UL ) + :( col_ ) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( col_ ) + :( col_+1UL ) ) + :( size() ) ); + + for( size_t j=jbegin; j // Type of the dense matrix +inline Column& + Column::operator=( initializer_list 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& Column::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_ 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& + Column::operator=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ tmp( right ); + smpAssign( left, tmp ); + } + else { + if( IsSparseVector::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& + Column::operator+=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAddAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& + Column::operator-=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !trySubAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& + Column::operator*=( const DenseVector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryMultAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& + Column::operator*=( const SparseVector& 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_ 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& + Column::operator/=( const DenseVector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryDivAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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, Column >& + Column::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, Column >& + Column::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::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::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::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::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& Column::scale( const Other& scalar ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( col_+1UL ) + :( col_ ) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( col_ ) + :( col_+1UL ) ) + :( size() ) ); + + for( size_t j=jbegin; j // Type of the dense matrix +template< typename Other > // Data type of the foreign expression +inline bool Column::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::canAlias( const Column* 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::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::isAliased( const Column* 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::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::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::SIMDType + Column::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::SIMDType + Column::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::SIMDType + Column::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::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::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::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::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::BLAZE_TEMPLATE VectorizedAssign > + Column::assign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Column::BLAZE_TEMPLATE VectorizedAssign > + Column::assign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ right( (~rhs).begin() ); + + if( useStreaming && columns > ( cacheSize/( sizeof(ElementType) * 3UL ) ) && !(~rhs).isAliased( this ) ) + { + for( ; j // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Column::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedAddAssign > + Column::addAssign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Column::BLAZE_TEMPLATE VectorizedAddAssign > + Column::addAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Column::addAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedSubAssign > + Column::subAssign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Column::BLAZE_TEMPLATE VectorizedSubAssign > + Column::subAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Column::subAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedMultAssign > + Column::multAssign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Column::BLAZE_TEMPLATE VectorizedMultAssign > + Column::multAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Column::multAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const ResultType tmp( serial( *this ) ); + + reset(); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedDivAssign > + Column::divAssign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Column::BLAZE_TEMPLATE VectorizedDivAssign > + Column::divAssign( const DenseVector& 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_ 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public SparseVector< Column, false > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Column This; //!< Type of this Column instance. + typedef SparseVector BaseType; //!< Base type of this Column instance. + typedef ColumnTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the column elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant column value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Iterator over constant elements. + typedef ConstIterator_ ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, Iterator_ > 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& rhs ); + template< typename VT > inline Column& operator= ( const SparseVector& rhs ); + template< typename VT > inline Column& operator+=( const DenseVector& rhs ); + template< typename VT > inline Column& operator+=( const SparseVector& rhs ); + template< typename VT > inline Column& operator-=( const DenseVector& rhs ); + template< typename VT > inline Column& operator-=( const SparseVector& rhs ); + template< typename VT > inline Column& operator*=( const Vector& rhs ); + template< typename VT > inline Column& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, Column >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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 & rhs ); + template< typename VT > inline void assign ( const SparseVector& rhs ); + template< typename VT > inline void addAssign( const DenseVector & rhs ); + template< typename VT > inline void addAssign( const SparseVector& rhs ); + template< typename VT > inline void subAssign( const DenseVector & rhs ); + template< typename VT > inline void subAssign( const SparseVector& 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& column ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend bool isSame( const Column& a, const Column& b ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAddAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool trySubAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryMultAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend DerestrictTrait_< Column > derestrict( Column& 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::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::Reference + Column::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::ConstReference + Column::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid column access index" ); + return const_cast( 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::Reference + Column::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::ConstReference + Column::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::Iterator Column::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::ConstIterator Column::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::ConstIterator Column::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::Iterator Column::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::ConstIterator Column::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::ConstIterator Column::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& Column::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_ 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& Column::operator=( const DenseVector& rhs ) +{ + using blaze::assign; + + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Column::operator=( const SparseVector& 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( size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Column::operator+=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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& Column::operator+=( const SparseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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& Column::operator-=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& Column::operator-=( const SparseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& Column::operator*=( const Vector& 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_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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_ 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& Column::operator/=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef DivTrait_< ResultType, ResultType_ > 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_ 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_, Column >& + Column::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_, Column >& + Column::operator/=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + typedef DivTrait_ DT; + typedef If_< IsNumeric
, DT, Other > Tmp; + + // Depending on the two involved data types, an integer division is applied or a + // floating point division is selected. + if( IsNumeric
::value && IsFloatingPoint
::value ) { + const Tmp tmp( Tmp(1)/static_cast( 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::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::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::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::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::Iterator + Column::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::Iterator + Column::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::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::Iterator Column::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::Iterator + Column::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::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& Column::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::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::Iterator Column::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::ConstIterator + Column::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::Iterator Column::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::ConstIterator + Column::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::Iterator Column::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::ConstIterator + Column::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::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::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::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::assign( const DenseVector& 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 // Symmetry flag +template< typename VT > // Type of the right-hand side sparse vector +inline void Column::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" ); + + for( ConstIterator_ 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::addAssign( const DenseVector& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::addAssign( const SparseVector& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::subAssign( const DenseVector& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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::subAssign( const SparseVector& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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 + : public SparseVector< Column, false > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Column This; //!< Type of this Column instance. + typedef SparseVector BaseType; //!< Base type of this Column instance. + typedef ColumnTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the column elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant column value. + typedef If_< IsConst, ConstReference, Reference_ > 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::value }; + //******************************************************************************************* + + //**Type definitions************************************************************************* + //! Type of the underlying sparse elements. + typedef typename std::iterator_traits::value_type SET; + + typedef Reference_ RT; //!< Reference type of the underlying sparse element. + typedef ConstReference_ CRT; //!< Reference-to-const type of the underlying sparse element. + //******************************************************************************************* + + public: + //**Type definitions************************************************************************* + typedef ValueType_ ValueType; //!< The value type of the row element. + typedef size_t IndexType; //!< The index type of the row element. + typedef IfTrue_ 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 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_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& 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_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& 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& 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_; ifind( 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_ > ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, ColumnIterator< MT, Iterator_ > > 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& rhs ); + template< typename VT > inline Column& operator+=( const Vector& rhs ); + template< typename VT > inline Column& operator-=( const Vector& rhs ); + template< typename VT > inline Column& operator*=( const Vector& rhs ); + template< typename VT > inline Column& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_, Column >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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 & rhs ); + template< typename VT > inline void assign ( const SparseVector& rhs ); + template< typename VT > inline void addAssign( const Vector& rhs ); + template< typename VT > inline void subAssign( const Vector& 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& column ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend bool isSame( const Column& a, const Column& b ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAddAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool trySubAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryMultAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend DerestrictTrait_< Column > derestrict( Column& 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::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::Reference + Column::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::ConstReference + Column::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid column access index" ); + return const_cast( 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::Reference + Column::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::ConstReference + Column::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::Iterator Column::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::ConstIterator + Column::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::ConstIterator + Column::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::Iterator Column::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::ConstIterator + Column::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::ConstIterator + Column::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& + Column::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_ 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& + Column::operator=( const Vector& rhs ) +{ + using blaze::assign; + + if( size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + const CompositeType_ tmp( ~rhs ); + + if( !tryAssign( matrix_, tmp, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ 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& + Column::operator+=( const Vector& 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_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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& + Column::operator-=( const Vector& 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_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& + Column::operator*=( const Vector& 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_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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_ 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& + Column::operator/=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef DivTrait_< ResultType, ResultType_ > 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_ 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_, Column >& + Column::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_, Column >& + Column::operator/=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + typedef DivTrait_ DT; + typedef If_< IsNumeric
, DT, Other > Tmp; + + // Depending on the two involved data types, an integer division is applied or a + // floating point division is selected. + if( IsNumeric
::value && IsFloatingPoint
::value ) { + const Tmp tmp( Tmp(1)/static_cast( 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::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::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::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::reset() +{ + const size_t ibegin( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( col_+1UL ) + :( col_ ) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( col_ ) + :( col_+1UL ) ) + :( size() ) ); + + for( size_t i=ibegin; i // Type of the sparse matrix +inline typename Column::Iterator + Column::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::Iterator + Column::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::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::Iterator + Column::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::Iterator + Column::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::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& Column::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::Iterator + Column::find( size_t index ) +{ + const Iterator_ 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::ConstIterator + Column::find( size_t index ) const +{ + const ConstIterator_ 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::Iterator + Column::lowerBound( size_t index ) +{ + for( size_t i=index; i 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::ConstIterator + Column::lowerBound( size_t index ) const +{ + for( size_t i=index; i 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::Iterator + Column::upperBound( size_t index ) +{ + for( size_t i=index+1UL; i 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::ConstIterator + Column::upperBound( size_t index ) const +{ + for( size_t i=index+1UL; i 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::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::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::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::assign( const DenseVector& 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::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + size_t i( 0UL ); + + for( ConstIterator_ element=(~rhs).begin(); element!=(~rhs).end(); ++element ) { + for( ; iindex(); ++i ) + matrix_.erase( i, col_ ); + matrix_(i++,col_) = element->value(); + } + for( ; i // Type of the sparse matrix +template< typename VT > // Type of the right-hand side vector +inline void Column::addAssign( const Vector& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::subAssign( const Vector& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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 + : public SparseVector< Column, false > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Column This; //!< Type of this Column instance. + typedef SparseVector BaseType; //!< Base type of this Column instance. + typedef ColumnTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the column elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant column value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Iterator over constant elements. + typedef ConstIterator_ ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, Iterator_ > 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& rhs ); + template< typename VT > inline Column& operator= ( const SparseVector& rhs ); + template< typename VT > inline Column& operator+=( const DenseVector& rhs ); + template< typename VT > inline Column& operator+=( const SparseVector& rhs ); + template< typename VT > inline Column& operator-=( const DenseVector& rhs ); + template< typename VT > inline Column& operator-=( const SparseVector& rhs ); + template< typename VT > inline Column& operator*=( const Vector& rhs ); + template< typename VT > inline Column& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_, Column >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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 & rhs ); + template< typename VT > inline void assign ( const SparseVector& rhs ); + template< typename VT > inline void addAssign( const DenseVector & rhs ); + template< typename VT > inline void addAssign( const SparseVector& rhs ); + template< typename VT > inline void subAssign( const DenseVector & rhs ); + template< typename VT > inline void subAssign( const SparseVector& 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& column ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend bool isSame( const Column& a, const Column& b ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAddAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool trySubAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryMultAssign( const Column& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend DerestrictTrait_< Column > derestrict( Column& 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::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::Reference + Column::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::ConstReference + Column::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid column access index" ); + return const_cast( 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::Reference + Column::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::ConstReference + Column::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::Iterator Column::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::ConstIterator + Column::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::ConstIterator + Column::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::Iterator Column::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::ConstIterator + Column::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::ConstIterator + Column::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& Column::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_ 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& + Column::operator=( const DenseVector& rhs ) +{ + using blaze::assign; + + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& + Column::operator=( const SparseVector& 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( size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, 0UL, col_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& + Column::operator+=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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& + Column::operator+=( const SparseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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& + Column::operator-=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& + Column::operator-=( const SparseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& + Column::operator*=( const Vector& 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_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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_ 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& + Column::operator/=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_COLUMN_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef DivTrait_< ResultType, ResultType_ > 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_ 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_, Column >& + Column::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_, Column >& + Column::operator/=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + typedef DivTrait_ DT; + typedef If_< IsNumeric
, DT, Other > Tmp; + + // Depending on the two involved data types, an integer division is applied or a + // floating point division is selected. + if( IsNumeric
::value && IsFloatingPoint
::value ) { + const Tmp tmp( Tmp(1)/static_cast( 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::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::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::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::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::Iterator + Column::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::Iterator + Column::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::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::Iterator + Column::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::Iterator + Column::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::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& Column::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::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::Iterator + Column::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::ConstIterator + Column::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::Iterator + Column::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::ConstIterator + Column::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::Iterator + Column::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::ConstIterator + Column::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::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::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::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::assign( const DenseVector& 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 // Type of the sparse matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Column::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" ); + + for( ConstIterator_ 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::addAssign( const DenseVector& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::addAssign( const SparseVector& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::subAssign( const DenseVector& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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::subAssign( const SparseVector& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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 +#include +#include +#include + + +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; + using SparseVectorType = blaze::CompressedVector; + using DenseMatrixType = blaze::DynamicMatrix; + using SparseMatrixType = blaze::CompressedMatrix; + + DenseVectorType x; + SparseVectorType y; + DenseMatrixType A, B; + SparseMatrixType C, D; + // ... Resizing and initialization + + // Setting the 2nd row of matrix A to x + blaze::Row 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; + MatrixType A; + // ... Resizing and initialization + + // Creating a view on the 4th row of matrix A + blaze::Row 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; + using RowType = blaze::Row; + + 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; + using RowType = blaze::Row; + + 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; + MatrixType A( 10UL, 100UL ); // Non-initialized 10x100 matrix + + using RowType = blaze::Row; + 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; + using RowType = blaze::Row; + + 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 a( 2UL, 2.0 ), b; + blaze::CompressedVector c( 2UL ); + c[1] = 3.0; + + using DenseMatrix = blaze::DynamicMatrix; + DenseMatrix A( 4UL, 2UL ); // Non-initialized 4x2 matrix + + using RowType = blaze::Row; + 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; + using RowType = blaze::Row; + + 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 A( 128UL, 128UL ); + blaze::DynamicMatrix B( 128UL, 128UL ); + // ... Resizing and initialization + + // The computation of the 15th row of the multiplication between A and B ... + blaze::DynamicVector 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 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::value // Storage order + , bool DF = IsDenseMatrix::value // Density flag + , bool SF = IsSymmetric::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public DenseVector< Row, true > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Row This; //!< Type of this Row instance. + typedef DenseVector BaseType; //!< Base type of this Row instance. + typedef RowTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the row elements. + typedef SIMDTrait_ SIMDType; //!< SIMD type of the row elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant row value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Pointer to a constant row value. + typedef const ElementType* ConstPointer; + + //! Pointer to a non-constant row value. + typedef If_< Or< IsConst, Not< HasMutableDataAccess > >, ConstPointer, ElementType* > Pointer; + + //! Iterator over constant elements. + typedef ConstIterator_ ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, Iterator_ > 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 list ); + inline Row& operator=( const Row& rhs ); + + template< typename VT > inline Row& operator= ( const Vector& rhs ); + template< typename VT > inline Row& operator+=( const Vector& rhs ); + template< typename VT > inline Row& operator-=( const Vector& rhs ); + template< typename VT > inline Row& operator*=( const DenseVector& rhs ); + template< typename VT > inline Row& operator*=( const SparseVector& rhs ); + template< typename VT > inline Row& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, Row >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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_ >::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_ >::value && + HasSIMDAdd< ElementType, ElementType_ >::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_ >::value && + HasSIMDSub< ElementType, ElementType_ >::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_ >::value && + HasSIMDMult< ElementType, ElementType_ >::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_ >::value && + HasSIMDDiv< ElementType, ElementType_ >::value }; + }; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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* 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* 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 > assign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedAssign > assign( const DenseVector& rhs ); + + template< typename VT > inline void assign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedAddAssign > addAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedAddAssign > addAssign( const DenseVector& rhs ); + + template< typename VT > inline void addAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedSubAssign > subAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedSubAssign > subAssign( const DenseVector& rhs ); + + template< typename VT > inline void subAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedMultAssign > multAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedMultAssign > multAssign( const DenseVector& rhs ); + + template< typename VT > inline void multAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedDivAssign > divAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedDivAssign > divAssign( const DenseVector& 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& row ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend bool isSame( const Row& a, const Row& b ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAddAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool trySubAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryMultAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2,bool SF2, typename VT > + friend bool tryDivAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend DerestrictTrait_< Row > derestrict( Row& 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::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::Reference Row::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::ConstReference + Row::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid row access index" ); + return const_cast( 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::Reference Row::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::ConstReference Row::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::Pointer Row::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::ConstPointer Row::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::Iterator Row::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::ConstIterator Row::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::ConstIterator Row::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::Iterator Row::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::ConstIterator Row::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::ConstIterator Row::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& Row::operator=( const ElementType& rhs ) +{ + const size_t jbegin( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( row_+1UL ) + :( row_ ) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( row_ ) + :( row_+1UL ) ) + :( size() ) ); + + for( size_t j=jbegin; j // Symmetry flag +inline Row& Row::operator=( initializer_list 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& Row::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_ 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& Row::operator=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ tmp( right ); + smpAssign( left, tmp ); + } + else { + if( IsSparseVector::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& Row::operator+=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAddAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Row::operator-=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !trySubAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Row::operator*=( const DenseVector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryMultAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Row::operator*=( const SparseVector& 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_ 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& Row::operator/=( const DenseVector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryDivAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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, Row >& + Row::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, Row >& + Row::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::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::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::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::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& Row::scale( const Other& scalar ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( row_+1UL ) + :( row_ ) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( row_ ) + :( row_+1UL ) ) + :( size() ) ); + + for( size_t j=jbegin; j // Symmetry flag +template< typename Other > // Data type of the foreign expression +inline bool Row::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::canAlias( const Row* 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::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::isAliased( const Row* 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::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::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::SIMDType + Row::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::SIMDType + Row::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::SIMDType + Row::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::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::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::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::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::BLAZE_TEMPLATE VectorizedAssign > + Row::assign( const DenseVector& 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 // Symmetry flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Row::BLAZE_TEMPLATE VectorizedAssign > + Row::assign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ right( (~rhs).begin() ); + + if( useStreaming && columns > ( cacheSize/( sizeof(ElementType) * 3UL ) ) && !(~rhs).isAliased( &matrix_ ) ) + { + for( ; j // Symmetry flag +template< typename VT > // Type of the right-hand side sparse vector +inline void Row::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedAddAssign > + Row::addAssign( const DenseVector& 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 // Symmetry flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Row::BLAZE_TEMPLATE VectorizedAddAssign > + Row::addAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ 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 // Symmetry flag +template< typename VT > // Type of the right-hand side sparse vector +inline void Row::addAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedSubAssign > + Row::subAssign( const DenseVector& 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 // Symmetry flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Row::BLAZE_TEMPLATE VectorizedSubAssign > + Row::subAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ 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 // Symmetry flag +template< typename VT > // Type of the right-hand side sparse vector +inline void Row::subAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedMultAssign > + Row::multAssign( const DenseVector& 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 // Symmetry flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Row::BLAZE_TEMPLATE VectorizedMultAssign > + Row::multAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ 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 // Symmetry flag +template< typename VT > // Type of the right-hand side sparse vector +inline void Row::multAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const ResultType tmp( serial( *this ) ); + + reset(); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedDivAssign > + Row::divAssign( const DenseVector& 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 // Symmetry flag +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Row::BLAZE_TEMPLATE VectorizedDivAssign > + Row::divAssign( const DenseVector& 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_ 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 // Type of the dense matrix +class Row + : public DenseVector< Row, true > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Row This; //!< Type of this Row instance. + typedef DenseVector BaseType; //!< Base type of this Row instance. + typedef RowTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the row elements. + typedef ElementType_ 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_ ConstReference; + + //! Reference to a non-constant row value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Pointer to a constant row value. + typedef const ElementType* ConstPointer; + + //! Pointer to a non-constant row value. + typedef If_< Or< IsConst, Not< HasMutableDataAccess > >, 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, ConstReference_, Reference_ > Reference; + + typedef std::random_access_iterator_tag IteratorCategory; //!< The iterator category. + typedef RemoveReference_ 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& 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& 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& 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& 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& 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& 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& 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 ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, RowIterator > 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 list ); + inline Row& operator=( const Row& rhs ); + + template< typename VT > inline Row& operator= ( const Vector& rhs ); + template< typename VT > inline Row& operator+=( const Vector& rhs ); + template< typename VT > inline Row& operator-=( const Vector& rhs ); + template< typename VT > inline Row& operator*=( const DenseVector& rhs ); + template< typename VT > inline Row& operator*=( const SparseVector& rhs ); + template< typename VT > inline Row& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, Row >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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* 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* alias ) const noexcept; + + inline bool isAligned () const noexcept; + inline bool canSMPAssign() const noexcept; + + template< typename VT > inline void assign ( const DenseVector & rhs ); + template< typename VT > inline void assign ( const SparseVector& rhs ); + template< typename VT > inline void addAssign ( const DenseVector & rhs ); + template< typename VT > inline void addAssign ( const SparseVector& rhs ); + template< typename VT > inline void subAssign ( const DenseVector & rhs ); + template< typename VT > inline void subAssign ( const SparseVector& rhs ); + template< typename VT > inline void multAssign( const DenseVector & rhs ); + template< typename VT > inline void multAssign( const SparseVector& rhs ); + template< typename VT > inline void divAssign ( const DenseVector & 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& row ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend bool isSame( const Row& a, const Row& b ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAddAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool trySubAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryMultAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryDivAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend DerestrictTrait_< Row > derestrict( Row& 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::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::Reference + Row::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::ConstReference + Row::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid row access index" ); + return const_cast( 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::Reference + Row::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::ConstReference + Row::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::Pointer Row::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::ConstPointer Row::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::Iterator Row::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::ConstIterator Row::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::ConstIterator Row::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::Iterator Row::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::ConstIterator Row::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::ConstIterator Row::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& Row::operator=( const ElementType& rhs ) +{ + const size_t jbegin( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( row_+1UL ) + :( row_ ) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( row_ ) + :( row_+1UL ) ) + :( size() ) ); + + for( size_t j=jbegin; j // Type of the dense matrix +inline Row& + Row::operator=( initializer_list 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& Row::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_ 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& Row::operator=( const Vector& 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType tmp( right ); + smpAssign( left, tmp ); + } + else { + if( IsSparseVector::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& Row::operator+=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAddAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Row::operator-=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !trySubAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Row::operator*=( const DenseVector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryMultAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Row::operator*=( const SparseVector& 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_ 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& Row::operator/=( const DenseVector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryDivAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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, Row >& + Row::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, Row >& + Row::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::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::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::nonZeros() const +{ + const size_t columns( size() ); + size_t nonzeros( 0UL ); + + for( size_t j=0UL; j // Type of the dense matrix +inline void Row::reset() +{ + using blaze::clear; + + const size_t jbegin( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( row_+1UL ) + :( row_ ) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( row_ ) + :( row_+1UL ) ) + :( size() ) ); + + for( size_t j=jbegin; j // Type of the dense matrix +template< typename Other > // Data type of the scalar value +inline Row& Row::scale( const Other& scalar ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + const size_t jbegin( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( row_+1UL ) + :( row_ ) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( row_ ) + :( row_+1UL ) ) + :( size() ) ); + + for( size_t j=jbegin; j // Type of the dense matrix +template< typename Other > // Data type of the foreign expression +inline bool Row::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::canAlias( const Row* 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::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::isAliased( const Row* 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::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::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::assign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Row::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::addAssign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Row::addAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::subAssign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Row::subAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::multAssign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Row::multAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const ResultType tmp( serial( *this ) ); + + reset(); + + for( ConstIterator_ 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::divAssign( const DenseVector& 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 // Type of the dense matrix +class Row + : public DenseVector< Row, true > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Row This; //!< Type of this Row instance. + typedef DenseVector BaseType; //!< Base type of this Row instance. + typedef RowTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the row elements. + typedef SIMDTrait_ SIMDType; //!< SIMD type of the row elements. + typedef ElementType_ 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_ ConstReference; + + //! Reference to a non-constant row value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Pointer to a constant row value. + typedef const ElementType* ConstPointer; + + //! Pointer to a non-constant row value. + typedef If_< Or< IsConst, Not< HasMutableDataAccess > >, ConstPointer, ElementType* > Pointer; + + //! Iterator over constant elements. + typedef ConstIterator_ ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, Iterator_ > 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 list ); + inline Row& operator=( const Row& rhs ); + + template< typename VT > inline Row& operator= ( const Vector& rhs ); + template< typename VT > inline Row& operator+=( const Vector& rhs ); + template< typename VT > inline Row& operator-=( const Vector& rhs ); + template< typename VT > inline Row& operator*=( const DenseVector& rhs ); + template< typename VT > inline Row& operator*=( const SparseVector& rhs ); + template< typename VT > inline Row& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, Row >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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_ >::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_ >::value && + HasSIMDAdd< ElementType, ElementType_ >::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_ >::value && + HasSIMDSub< ElementType, ElementType_ >::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_ >::value && + HasSIMDMult< ElementType, ElementType_ >::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_ >::value && + HasSIMDDiv< ElementType, ElementType_ >::value }; + }; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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* 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* 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 > assign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedAssign > assign( const DenseVector& rhs ); + + template< typename VT > inline void assign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedAddAssign > addAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedAddAssign > addAssign( const DenseVector& rhs ); + + template< typename VT > inline void addAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedSubAssign > subAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedSubAssign > subAssign( const DenseVector& rhs ); + + template< typename VT > inline void subAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedMultAssign > multAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedMultAssign > multAssign( const DenseVector& rhs ); + + template< typename VT > inline void multAssign( const SparseVector& rhs ); + + template< typename VT > + inline DisableIf_< VectorizedDivAssign > divAssign( const DenseVector& rhs ); + + template< typename VT > + inline EnableIf_< VectorizedDivAssign > divAssign( const DenseVector& 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& row ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend bool isSame( const Row& a, const Row& b ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAddAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool trySubAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryMultAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryDivAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend DerestrictTrait_< Row > derestrict( Row& 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::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::Reference + Row::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::ConstReference + Row::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid row access index" ); + return const_cast( 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::Reference + Row::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::ConstReference + Row::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::Pointer Row::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::ConstPointer Row::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::Iterator Row::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::ConstIterator Row::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::ConstIterator Row::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::Iterator Row::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::ConstIterator Row::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::ConstIterator Row::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& Row::operator=( const ElementType& rhs ) +{ + const size_t ibegin( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( row_+1UL ) + :( row_ ) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( row_ ) + :( row_+1UL ) ) + :( size() ) ); + + for( size_t i=ibegin; i // Type of the dense matrix +inline Row& + Row::operator=( initializer_list 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& Row::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_ 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& Row::operator=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ tmp( right ); + smpAssign( left, tmp ); + } + else { + if( IsSparseVector::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& Row::operator+=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAddAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Row::operator-=( const Vector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !trySubAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Row::operator*=( const DenseVector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryMultAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Row::operator*=( const SparseVector& 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_ 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& Row::operator/=( const DenseVector& rhs ) +{ + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryDivAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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, Row >& + Row::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, Row >& + Row::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::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::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::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::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& Row::scale( const Other& scalar ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + const size_t ibegin( ( IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( row_+1UL ) + :( row_ ) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( row_ ) + :( row_+1UL ) ) + :( size() ) ); + + for( size_t i=ibegin; i // Type of the dense matrix +template< typename Other > // Data type of the foreign expression +inline bool Row::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::canAlias( const Row* 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::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::isAliased( const Row* 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::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::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::SIMDType + Row::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::SIMDType + Row::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::SIMDType + Row::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::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::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::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::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::BLAZE_TEMPLATE VectorizedAssign > + Row::assign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Row::BLAZE_TEMPLATE VectorizedAssign > + Row::assign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ right( (~rhs).begin() ); + + if( useStreaming && rows > ( cacheSize/( sizeof(ElementType) * 3UL ) ) && !(~rhs).isAliased( &matrix_ ) ) + { + for( ; i // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Row::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedAddAssign > + Row::addAssign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Row::BLAZE_TEMPLATE VectorizedAddAssign > + Row::addAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Row::addAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedSubAssign > + Row::subAssign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Row::BLAZE_TEMPLATE VectorizedSubAssign > + Row::subAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Row::subAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedMultAssign > + Row::multAssign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Row::BLAZE_TEMPLATE VectorizedMultAssign > + Row::multAssign( const DenseVector& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_VECTORIZABLE_TYPE( ElementType ); + + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const bool remainder( !IsPadded::value || !IsPadded::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_ 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Row::multAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const ResultType tmp( serial( *this ) ); + + reset(); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedDivAssign > + Row::divAssign( const DenseVector& 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 // Type of the dense matrix +template< typename VT > // Type of the right-hand side dense vector +inline EnableIf_< typename Row::BLAZE_TEMPLATE VectorizedDivAssign > + Row::divAssign( const DenseVector& 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_ 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public SparseVector< Row, true > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the sparse matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Row This; //!< Type of this Row instance. + typedef SparseVector BaseType; //!< Base type of this Row instance. + typedef RowTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the row elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant row value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Iterator over constant elements. + typedef ConstIterator_ ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, Iterator_ > 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& rhs ); + template< typename VT > inline Row& operator= ( const SparseVector& rhs ); + template< typename VT > inline Row& operator+=( const DenseVector& rhs ); + template< typename VT > inline Row& operator+=( const SparseVector& rhs ); + template< typename VT > inline Row& operator-=( const DenseVector& rhs ); + template< typename VT > inline Row& operator-=( const SparseVector& rhs ); + template< typename VT > inline Row& operator*=( const Vector& rhs ); + template< typename VT > inline Row& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_, Row >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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 & rhs ); + template< typename VT > inline void assign ( const SparseVector& rhs ); + template< typename VT > inline void addAssign( const DenseVector & rhs ); + template< typename VT > inline void addAssign( const SparseVector& rhs ); + template< typename VT > inline void subAssign( const DenseVector & rhs ); + template< typename VT > inline void subAssign( const SparseVector& 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& row ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend bool isSame( const Row& a, const Row& b ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAddAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool trySubAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryMultAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend DerestrictTrait_< Row > derestrict( Row& 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::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::Reference Row::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::ConstReference + Row::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid row access index" ); + return const_cast( 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::Reference Row::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::ConstReference Row::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::Iterator Row::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::ConstIterator Row::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::ConstIterator Row::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::Iterator Row::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::ConstIterator Row::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::ConstIterator Row::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& Row::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_ 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& Row::operator=( const DenseVector& rhs ) +{ + using blaze::assign; + + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Row::operator=( const SparseVector& 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( size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& Row::operator+=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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& Row::operator+=( const SparseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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& Row::operator-=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& Row::operator-=( const SparseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& Row::operator*=( const Vector& 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_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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_ 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& Row::operator/=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef DivTrait_< ResultType, ResultType_ > 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_ 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_, Row >& + Row::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_, Row >& + Row::operator/=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + typedef DivTrait_ DT; + typedef If_< IsNumeric
, DT, Other > Tmp; + + // Depending on the two involved data types, an integer division is applied or a + // floating point division is selected. + if( IsNumeric
::value && IsFloatingPoint
::value ) { + const Tmp tmp( Tmp(1)/static_cast( 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::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::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::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::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::Iterator + Row::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::Iterator + Row::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::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::Iterator Row::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::Iterator + Row::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::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& Row::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::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::Iterator Row::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::ConstIterator Row::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::Iterator Row::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::ConstIterator Row::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::Iterator Row::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::ConstIterator Row::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::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::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::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::assign( const DenseVector& 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 // Symmetry flag +template< typename VT > // Type of the right-hand side sparse vector +inline void Row::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" ); + + for( ConstIterator_ 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::addAssign( const DenseVector& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::addAssign( const SparseVector& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::subAssign( const DenseVector& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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::subAssign( const SparseVector& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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 + : public SparseVector< Row, true > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the sparse matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Row This; //!< Type of this Row instance. + typedef SparseVector BaseType; //!< Base type of this Row instance. + typedef RowTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the row elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant row value. + typedef If_< IsConst, ConstReference, Reference_ > 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::value }; + //******************************************************************************************* + + //**Type definitions************************************************************************* + //! Type of the underlying sparse elements. + typedef typename std::iterator_traits::value_type SET; + + typedef Reference_ RT; //!< Reference type of the underlying sparse element. + typedef ConstReference_ CRT; //!< Reference-to-const type of the underlying sparse element. + //******************************************************************************************* + + public: + //**Type definitions************************************************************************* + typedef ValueType_ ValueType; //!< The value type of the row element. + typedef size_t IndexType; //!< The index type of the row element. + typedef IfTrue_ 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 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_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& 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_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& 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& 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_; jfind( 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_ > ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, RowIterator< MT, Iterator_ > > 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& rhs ); + template< typename VT > inline Row& operator+=( const Vector& rhs ); + template< typename VT > inline Row& operator-=( const Vector& rhs ); + template< typename VT > inline Row& operator*=( const Vector& rhs ); + template< typename VT > inline Row& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_, Row >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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 & rhs ); + template< typename VT > inline void assign ( const SparseVector& rhs ); + template< typename VT > inline void addAssign( const Vector& rhs ); + template< typename VT > inline void subAssign( const Vector& 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& row ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend bool isSame( const Row& a, const Row& b ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAddAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool trySubAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryMultAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend DerestrictTrait_< Row > derestrict( Row& 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::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::Reference + Row::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::ConstReference + Row::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid row access index" ); + return const_cast( 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::Reference + Row::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::ConstReference + Row::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::Iterator Row::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::ConstIterator Row::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::ConstIterator Row::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::Iterator Row::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::ConstIterator Row::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::ConstIterator Row::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& Row::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_ 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& Row::operator=( const Vector& rhs ) +{ + using blaze::assign; + + if( size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + const CompositeType_ tmp( ~rhs ); + + if( !tryAssign( matrix_, tmp, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ 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& Row::operator+=( const Vector& 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_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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& Row::operator-=( const Vector& 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_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& Row::operator*=( const Vector& 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_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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_ 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& + Row::operator/=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef DivTrait_< ResultType, ResultType_ > 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_ 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_, Row >& + Row::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_, Row >& + Row::operator/=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + typedef DivTrait_ DT; + typedef If_< IsNumeric
, DT, Other > Tmp; + + // Depending on the two involved data types, an integer division is applied or a + // floating point division is selected. + if( IsNumeric
::value && IsFloatingPoint
::value ) { + const Tmp tmp( Tmp(1)/static_cast( 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::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::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::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::reset() +{ + const size_t jbegin( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( row_+1UL ) + :( row_ ) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( row_ ) + :( row_+1UL ) ) + :( size() ) ); + + for( size_t j=jbegin; j // Type of the sparse matrix +inline typename Row::Iterator + Row::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::Iterator + Row::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::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::Iterator Row::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::Iterator + Row::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::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& Row::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::Iterator Row::find( size_t index ) +{ + const Iterator_ 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::ConstIterator + Row::find( size_t index ) const +{ + const ConstIterator_ 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::Iterator + Row::lowerBound( size_t index ) +{ + for( size_t i=index; i 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::ConstIterator + Row::lowerBound( size_t index ) const +{ + for( size_t i=index; i 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::Iterator + Row::upperBound( size_t index ) +{ + for( size_t i=index+1UL; i 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::ConstIterator + Row::upperBound( size_t index ) const +{ + for( size_t i=index+1UL; i 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::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::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::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::assign( const DenseVector& 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::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + size_t j( 0UL ); + + for( ConstIterator_ element=(~rhs).begin(); element!=(~rhs).end(); ++element ) { + for( ; jindex(); ++j ) + matrix_.erase( row_, j ); + matrix_(row_,j++) = element->value(); + } + for( ; j // Type of the sparse matrix +template< typename VT > // Type of the right-hand side vector +inline void Row::addAssign( const Vector& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::subAssign( const Vector& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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 + : public SparseVector< Row, true > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the sparse matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Row This; //!< Type of this Row instance. + typedef SparseVector BaseType; //!< Base type of this Row instance. + typedef RowTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the row elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant row value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Iterator over constant elements. + typedef ConstIterator_ ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, Iterator_ > 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& rhs ); + template< typename VT > inline Row& operator= ( const SparseVector& rhs ); + template< typename VT > inline Row& operator+=( const DenseVector& rhs ); + template< typename VT > inline Row& operator+=( const SparseVector& rhs ); + template< typename VT > inline Row& operator-=( const DenseVector& rhs ); + template< typename VT > inline Row& operator-=( const SparseVector& rhs ); + template< typename VT > inline Row& operator*=( const Vector& rhs ); + template< typename VT > inline Row& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_, Row >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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 & rhs ); + template< typename VT > inline void assign ( const SparseVector& rhs ); + template< typename VT > inline void addAssign( const DenseVector & rhs ); + template< typename VT > inline void addAssign( const SparseVector& rhs ); + template< typename VT > inline void subAssign( const DenseVector & rhs ); + template< typename VT > inline void subAssign( const SparseVector& 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& row ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend bool isSame( const Row& a, const Row& b ) noexcept; + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryAddAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool trySubAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2, typename VT > + friend bool tryMultAssign( const Row& lhs, const Vector& rhs, size_t index ); + + template< typename MT2, bool SO2, bool DF2, bool SF2 > + friend DerestrictTrait_< Row > derestrict( Row& 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::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::Reference + Row::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::ConstReference + Row::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid row access index" ); + return const_cast( 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::Reference + Row::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::ConstReference + Row::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::Iterator Row::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::ConstIterator Row::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::ConstIterator Row::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::Iterator Row::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::ConstIterator Row::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::ConstIterator Row::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& Row::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_ 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& + Row::operator=( const DenseVector& rhs ) +{ + using blaze::assign; + + 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, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& + Row::operator=( const SparseVector& 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( size() != (~rhs).size() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Vector sizes do not match" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, row_, 0UL ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& + Row::operator+=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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& + Row::operator+=( const SparseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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& + Row::operator-=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& + Row::operator-=( const SparseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& + Row::operator*=( const Vector& 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_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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_ 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& + Row::operator/=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_BE_ROW_VECTOR_TYPE ( ResultType_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef DivTrait_< ResultType, ResultType_ > 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_ 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_, Row >& + Row::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_, Row >& + Row::operator/=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + typedef DivTrait_ DT; + typedef If_< IsNumeric
, DT, Other > Tmp; + + // Depending on the two involved data types, an integer division is applied or a + // floating point division is selected. + if( IsNumeric
::value && IsFloatingPoint
::value ) { + const Tmp tmp( Tmp(1)/static_cast( 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::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::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::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::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::Iterator + Row::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::Iterator + Row::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::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::Iterator + Row::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::Iterator + Row::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::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& Row::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::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::Iterator + Row::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::ConstIterator + Row::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::Iterator + Row::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::ConstIterator + Row::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::Iterator + Row::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::ConstIterator + Row::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::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::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::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::assign( const DenseVector& 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 // Type of the sparse matrix +template< typename VT > // Type of the right-hand side sparse vector +inline void Row::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + BLAZE_INTERNAL_ASSERT( nonZeros() == 0UL, "Invalid non-zero elements detected" ); + + for( ConstIterator_ 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::addAssign( const DenseVector& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::addAssign( const SparseVector& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::subAssign( const DenseVector& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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::subAssign( const SparseVector& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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 +#include +#include + + +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; + + DenseMatrixType A; + // ... Resizing and initialization + + // Creating a dense submatrix of size 8x16, starting in row 0 and column 4 + blaze::Submatrix sm = submatrix( A, 0UL, 4UL, 8UL, 16UL ); + \endcode + + \code + using SparseMatrixType = blaze::CompressedMatrix; + + SparseMatrixType A; + // ... Resizing and initialization + + // Creating a sparse submatrix of size 8x16, starting in row 0 and column 4 + blaze::Submatrix 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; + using SparseMatrixType = blaze::CompressedMatrix; + + DenseMatrixType A, B; + SparseMatrixType C; + // ... Resizing and initialization + + // Creating a dense submatrix of size 8x4, starting in row 0 and column 2 + blaze::Submatrix 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; + MatrixType A; + // ... Resizing and initialization + + // Creating a 8x8 submatrix, starting from position (4,4) + blaze::Submatrix 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; + using SubmatrixType = blaze::Submatrix; + + 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; + using SubmatrixType = blaze::Submatrix; + + 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; + MatrixType A( 256UL, 512UL ); // Non-initialized matrix of size 256x512 + + using SubmatrixType = blaze::Submatrix; + 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; + using SubmatrixType = blaze::Submatrix; + + 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; + using SparseMatrixType = blaze::CompressedMatrix; + DenseMatrixType D1, D2, D3; + SparseMatrixType S1, S2; + + using SparseVectorType = blaze::CompressedVector; + SparseVectorType a, b; + + // ... Resizing and initialization + + using SubmatrixType = blaze::Submatrix; + 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; + + DenseMatrixType A; + // ... Resizing and initialization + + // Identical creations of an unaligned submatrix of size 8x8, starting in row 0 and column 0 + blaze::Submatrix sm1 = submatrix ( A, 0UL, 0UL, 8UL, 8UL ); + blaze::Submatrix sm2 = submatrix( A, 0UL, 0UL, 8UL, 8UL ); + blaze::Submatrix sm3 = submatrix ( A, 0UL, 0UL, 8UL, 8UL ); + blaze::Submatrix sm4 = submatrix( 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 sv = submatrix( 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; + using SubmatrixType = blaze::Submatrix; + + 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( 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( 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( D, 4UL, 0UL, 9UL, 17UL ); + + // Error: First row is not a multiple of 4 + SubmatrixType dsm4 = submatrix( D, 2UL, 4UL, 12UL, 12UL ); + + // Error: First column is not a multiple of 4 + SubmatrixType dsm5 = submatrix( 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( 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( 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; + + SparseMatrixType A; + // ... Resizing and initialization + + // Creating an aligned submatrix of size 8x8, starting in row 0 and column 0 + blaze::Submatrix sv = submatrix( 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; + using SubmatrixType = blaze::Submatrix; + + 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 >; + 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 > A1( 4 ), A2( 4 ); + + // Setup of the 3x2 dynamic matrix + // + // ( 0 9 ) + // B = ( 9 8 ) + // ( 0 7 ) + // + DynamicMatrix 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::value // Storage order + , bool DF = IsDenseMatrix::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public DenseMatrix< Submatrix, false > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Submatrix This; //!< Type of this Submatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this Submatrix instance. + typedef SubmatrixTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the submatrix elements. + typedef SIMDTrait_ SIMDType; //!< SIMD type of the submatrix elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant submatrix value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Pointer to a constant submatrix value. + typedef const ElementType* ConstPointer; + + //! Pointer to a non-constant submatrix value. + typedef If_< Or< IsConst, Not< HasMutableDataAccess > >, 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::iterator_category IteratorCategory; + + //! Type of the underlying elements. + typedef typename std::iterator_traits::value_type ValueType; + + //! Pointer return type. + typedef typename std::iterator_traits::pointer PointerType; + + //! Reference return type. + typedef typename std::iterator_traits::reference ReferenceType; + + //! Difference between two iterators. + typedef typename std::iterator_traits::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& 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_ > ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, SubmatrixIterator< Iterator_ > > 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 > list ); + inline Submatrix& operator=( const Submatrix& rhs ); + + template< typename MT2, bool SO2 > + inline Submatrix& operator=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline DisableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline EnableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO2 > + inline Submatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, Submatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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_ >::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_ >::value && + HasSIMDAdd< ElementType, ElementType_ >::value && + !IsDiagonal::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_ >::value && + HasSIMDSub< ElementType, ElementType_ >::value && + !IsDiagonal::value }; + }; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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* 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* 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 > assign( const DenseMatrix& rhs ); + + template< typename MT2 > + inline EnableIf_< VectorizedAssign > assign( const DenseMatrix& rhs ); + + template< typename MT2 > inline void assign( const DenseMatrix& rhs ); + template< typename MT2 > inline void assign( const SparseMatrix& rhs ); + template< typename MT2 > inline void assign( const SparseMatrix& rhs ); + + template< typename MT2 > + inline DisableIf_< VectorizedAddAssign > addAssign( const DenseMatrix& rhs ); + + template< typename MT2 > + inline EnableIf_< VectorizedAddAssign > addAssign( const DenseMatrix& rhs ); + + template< typename MT2 > inline void addAssign( const DenseMatrix& rhs ); + template< typename MT2 > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT2 > inline void addAssign( const SparseMatrix& rhs ); + + template< typename MT2 > + inline DisableIf_< VectorizedSubAssign > subAssign( const DenseMatrix& rhs ); + + template< typename MT2 > + inline EnableIf_< VectorizedSubAssign > subAssign( const DenseMatrix& rhs ); + + template< typename MT2 > inline void subAssign( const DenseMatrix& rhs ); + template< typename MT2 > inline void subAssign( const SparseMatrix& rhs ); + template< typename MT2 > inline void subAssign( const SparseMatrix& 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 + submatrix( const Submatrix& 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& sm ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Submatrix& a, const Matrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Matrix& a, const Submatrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Submatrix& a, const Submatrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF > + friend bool tryAssign( const Submatrix& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& rhs, + size_t row, size_t column ); + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend DerestrictTrait_< Submatrix > derestrict( Submatrix& 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::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::Reference + Submatrix::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::ConstReference + Submatrix::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( 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::Reference + Submatrix::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::ConstReference + Submatrix::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::Pointer + Submatrix::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::ConstPointer + Submatrix::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::Pointer + Submatrix::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::ConstPointer + Submatrix::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::Iterator + Submatrix::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::ConstIterator + Submatrix::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::ConstIterator + Submatrix::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::Iterator + Submatrix::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::ConstIterator + Submatrix::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::ConstIterator + Submatrix::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& + Submatrix::operator=( const ElementType& rhs ) +{ + const size_t iend( row_ + m_ ); + + for( size_t i=row_; i::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( max( i+1UL, column_ ) ) + :( max( i, column_ ) ) ) + :( column_ ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( min( i, column_+n_ ) ) + :( min( i+1UL, column_+n_ ) ) ) + :( column_+n_ ) ); + + for( size_t j=jbegin; j // Type of the dense matrix +inline Submatrix& + Submatrix::operator=( initializer_list< initializer_list > 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& + Submatrix::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_ 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& + Submatrix::operator=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + typedef If_< IsRestricted, CompositeType_, const MT2& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, row_, column_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + if( IsSparseMatrix::value ) + reset(); + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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, RequiresEvaluation >, Submatrix& > + Submatrix::operator+=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ left( derestrict( *this ) ); + + if( ( ( IsSymmetric::value || IsHermitian::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, RequiresEvaluation >, Submatrix& > + Submatrix::operator+=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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, RequiresEvaluation >, Submatrix& > + Submatrix::operator-=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ left( derestrict( *this ) ); + + if( ( ( IsSymmetric::value || IsHermitian::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, RequiresEvaluation >, Submatrix& > + Submatrix::operator-=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& + Submatrix::operator*=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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_ 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, Submatrix >& + Submatrix::operator*=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + DerestrictTrait_ 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, Submatrix >& + Submatrix::operator/=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + DerestrictTrait_ 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::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::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::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::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::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::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::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::nonZeros() const +{ + const size_t iend( row_ + m_ ); + const size_t jend( column_ + n_ ); + size_t nonzeros( 0UL ); + + for( size_t i=row_; i // Type of the dense matrix +inline size_t Submatrix::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 // Type of the dense matrix +inline void Submatrix::reset() +{ + using blaze::clear; + + for( size_t i=row_; i::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( max( i+1UL, column_ ) ) + :( max( i, column_ ) ) ) + :( column_ ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( min( i, column_+n_ ) ) + :( min( i+1UL, column_+n_ ) ) ) + :( column_+n_ ) ); + + for( size_t j=jbegin; j // Type of the dense matrix +inline void Submatrix::reset( size_t i ) +{ + using blaze::clear; + + BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" ); + + const size_t jbegin( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( max( i+1UL, column_ ) ) + :( max( i, column_ ) ) ) + :( column_ ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( min( i, column_+n_ ) ) + :( min( i+1UL, column_+n_ ) ) ) + :( column_+n_ ) ); + + for( size_t j=jbegin; j // Type of the dense matrix +inline Submatrix& Submatrix::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_ 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& Submatrix::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_ 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& + Submatrix::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::value ) + ?( ( IsStrictlyUpper::value ) + ?( max( i+1UL, column_ ) ) + :( max( i, column_ ) ) ) + :( column_ ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( min( i, column_+n_ ) ) + :( min( i+1UL, column_+n_ ) ) ) + :( column_+n_ ) ); + + for( size_t j=jbegin; j // Type of the dense matrix +inline bool Submatrix::hasOverlap() const noexcept +{ + BLAZE_INTERNAL_ASSERT( IsSymmetric::value || IsHermitian::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::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::canAlias( const Submatrix* 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::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::isAliased( const Submatrix* 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::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::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::SIMDType + Submatrix::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::SIMDType + Submatrix::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::SIMDType + Submatrix::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::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::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::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::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::BLAZE_TEMPLATE VectorizedAssign > + Submatrix::assign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline EnableIf_< typename Submatrix::BLAZE_TEMPLATE VectorizedAssign > + Submatrix::assign( const DenseMatrix& 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 right( (~rhs).begin(i) ); + + for( ; j 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline void Submatrix::assign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void Submatrix::assign( const SparseMatrix& 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 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::assign( const SparseMatrix& 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 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::BLAZE_TEMPLATE VectorizedAddAssign > + Submatrix::addAssign( const DenseMatrix& 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::value ) { + matrix_(row_+i,column_+i) += (~rhs)(i,i); + } + else { + for( size_t j=0UL; j // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline EnableIf_< typename Submatrix::BLAZE_TEMPLATE VectorizedAddAssign > + Submatrix::addAssign( const DenseMatrix& 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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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_ 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline void Submatrix::addAssign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void Submatrix::addAssign( const SparseMatrix& 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 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::addAssign( const SparseMatrix& 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 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::BLAZE_TEMPLATE VectorizedSubAssign > + Submatrix::subAssign( const DenseMatrix& 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::value ) { + matrix_(row_+i,column_+i) -= (~rhs)(i,i); + } + else { + for( size_t j=0UL; j // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline EnableIf_< typename Submatrix::BLAZE_TEMPLATE VectorizedSubAssign > + Submatrix::subAssign( const DenseMatrix& 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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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_ 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline void Submatrix::subAssign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void Submatrix::subAssign( const SparseMatrix& 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 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::subAssign( const SparseMatrix& 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 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 + : public DenseMatrix< Submatrix, true > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Submatrix This; //!< Type of this Submatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this Submatrix instance. + typedef SubmatrixTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the submatrix elements. + typedef SIMDTrait_ SIMDType; //!< SIMD type of the submatrix elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant submatrix value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Pointer to a constant submatrix value. + typedef const ElementType* ConstPointer; + + //! Pointer to a non-constant submatrix value. + typedef If_< Or< IsConst, Not< HasMutableDataAccess > >, 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::iterator_category IteratorCategory; + + //! Type of the underlying elements. + typedef typename std::iterator_traits::value_type ValueType; + + //! Pointer return type. + typedef typename std::iterator_traits::pointer PointerType; + + //! Reference return type. + typedef typename std::iterator_traits::reference ReferenceType; + + //! Difference between two iterators. + typedef typename std::iterator_traits::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& 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_ > ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, SubmatrixIterator< Iterator_ > > 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 > list ); + inline Submatrix& operator=( const Submatrix& rhs ); + + template< typename MT2, bool SO > + inline Submatrix& operator=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline DisableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline EnableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline DisableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline EnableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline Submatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, Submatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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_ >::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_ >::value && + HasSIMDAdd< ElementType, ElementType_ >::value && + !IsDiagonal::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_ >::value && + HasSIMDSub< ElementType, ElementType_ >::value && + !IsDiagonal::value }; + }; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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* 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* 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 > assign( const DenseMatrix& rhs ); + + template< typename MT2 > + inline EnableIf_< VectorizedAssign > assign( const DenseMatrix& rhs ); + + template< typename MT2 > inline void assign( const DenseMatrix& rhs ); + template< typename MT2 > inline void assign( const SparseMatrix& rhs ); + template< typename MT2 > inline void assign( const SparseMatrix& rhs ); + + template< typename MT2 > + inline DisableIf_< VectorizedAddAssign > addAssign( const DenseMatrix& rhs ); + + template< typename MT2 > + inline EnableIf_< VectorizedAddAssign > addAssign( const DenseMatrix& rhs ); + + template< typename MT2 > inline void addAssign( const DenseMatrix& rhs ); + template< typename MT2 > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT2 > inline void addAssign( const SparseMatrix& rhs ); + + template< typename MT2 > + inline DisableIf_< VectorizedSubAssign > subAssign( const DenseMatrix& rhs ); + + template< typename MT2 > + inline EnableIf_< VectorizedSubAssign > subAssign( const DenseMatrix& rhs ); + + template< typename MT2 > inline void subAssign( const DenseMatrix& rhs ); + template< typename MT2 > inline void subAssign( const SparseMatrix& rhs ); + template< typename MT2 > inline void subAssign( const SparseMatrix& 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 + submatrix( const Submatrix& 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& sm ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Submatrix& a, const Matrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Matrix& a, const Submatrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Submatrix& a, const Submatrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF > + friend bool tryAssign( const Submatrix& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& rhs, + size_t row, size_t column ); + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend DerestrictTrait_< Submatrix > derestrict( Submatrix& 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::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::Reference + Submatrix::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::ConstReference + Submatrix::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( 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::Reference + Submatrix::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::ConstReference + Submatrix::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::Pointer + Submatrix::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::ConstPointer + Submatrix::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::Pointer + Submatrix::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::ConstPointer + Submatrix::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::Iterator + Submatrix::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::ConstIterator + Submatrix::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::ConstIterator + Submatrix::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::Iterator + Submatrix::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::ConstIterator + Submatrix::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::ConstIterator + Submatrix::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& + Submatrix::operator=( const ElementType& rhs ) +{ + const size_t jend( column_ + n_ ); + + for( size_t j=column_; j::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( max( j+1UL, row_ ) ) + :( max( j, row_ ) ) ) + :( row_ ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( min( j, row_+m_ ) ) + :( min( j+1UL, row_+m_ ) ) ) + :( row_+m_ ) ); + + for( size_t i=ibegin; i // Type of the dense matrix +inline Submatrix& + Submatrix::operator=( initializer_list< initializer_list > 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 // Type of the dense matrix +inline Submatrix& + Submatrix::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_ 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& + Submatrix::operator=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + typedef If_< IsRestricted, CompositeType_, const MT2& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, row_, column_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + if( IsSparseMatrix::value ) + reset(); + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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, RequiresEvaluation >, Submatrix& > + Submatrix::operator+=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ left( derestrict( *this ) ); + + if( ( ( IsSymmetric::value || IsHermitian::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, RequiresEvaluation >, Submatrix& > + Submatrix::operator+=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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, RequiresEvaluation >, Submatrix& > + Submatrix::operator-=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ left( derestrict( *this ) ); + + if( ( ( IsSymmetric::value || IsHermitian::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, RequiresEvaluation >, Submatrix& > + Submatrix::operator-=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& + Submatrix::operator*=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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_ 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, Submatrix >& + Submatrix::operator*=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + DerestrictTrait_ 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, Submatrix >& + Submatrix::operator/=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + DerestrictTrait_ 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::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::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::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::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::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::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::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::nonZeros() const +{ + const size_t iend( row_ + m_ ); + const size_t jend( column_ + n_ ); + size_t nonzeros( 0UL ); + + for( size_t j=column_; j // Type of the dense matrix +inline size_t Submatrix::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 // Type of the dense matrix +inline void Submatrix::reset() +{ + using blaze::clear; + + for( size_t j=column_; j::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( max( j+1UL, row_ ) ) + :( max( j, row_ ) ) ) + :( row_ ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( min( j, row_+m_ ) ) + :( min( j+1UL, row_+m_ ) ) ) + :( row_+m_ ) ); + + for( size_t i=ibegin; i // Type of the dense matrix +inline void Submatrix::reset( size_t j ) +{ + using blaze::clear; + + BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" ); + + const size_t ibegin( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( max( j+1UL, row_ ) ) + :( max( j, row_ ) ) ) + :( row_ ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( min( j, row_+m_ ) ) + :( min( j+1UL, row_+m_ ) ) ) + :( row_+m_ ) ); + + for( size_t i=ibegin; i // Type of the dense matrix +inline Submatrix& Submatrix::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_ 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& Submatrix::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_ 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& Submatrix::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::value ) + ?( ( IsStrictlyLower::value ) + ?( max( j+1UL, row_ ) ) + :( max( j, row_ ) ) ) + :( row_ ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( min( j, row_+m_ ) ) + :( min( j+1UL, row_+m_ ) ) ) + :( row_+m_ ) ); + + for( size_t i=ibegin; i // Type of the dense matrix +inline bool Submatrix::hasOverlap() const noexcept +{ + BLAZE_INTERNAL_ASSERT( IsSymmetric::value || IsHermitian::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::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::canAlias( const Submatrix* 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::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::isAliased( const Submatrix* 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::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::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::SIMDType + Submatrix::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::SIMDType + Submatrix::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::SIMDType + Submatrix::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::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::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::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::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::BLAZE_TEMPLATE VectorizedAssign > + Submatrix::assign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline EnableIf_< typename Submatrix::BLAZE_TEMPLATE VectorizedAssign > + Submatrix::assign( const DenseMatrix& 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 right( (~rhs).begin(j) ); + + for( ; i 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline void Submatrix::assign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void Submatrix::assign( const SparseMatrix& 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 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::assign( const SparseMatrix& 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 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::BLAZE_TEMPLATE VectorizedAddAssign > + Submatrix::addAssign( const DenseMatrix& 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::value ) { + matrix_(row_+j,column_+j) += (~rhs)(j,j); + } + else { + for( size_t i=0UL; i // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline EnableIf_< typename Submatrix::BLAZE_TEMPLATE VectorizedAddAssign > + Submatrix::addAssign( const DenseMatrix& 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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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_ 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline void Submatrix::addAssign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void Submatrix::addAssign( const SparseMatrix& 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 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::addAssign( const SparseMatrix& 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 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::BLAZE_TEMPLATE VectorizedSubAssign > + Submatrix::subAssign( const DenseMatrix& 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::value ) { + matrix_(row_+j,column_+j) -= (~rhs)(j,j); + } + else { + for( size_t i=0UL; i // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline EnableIf_< typename Submatrix::BLAZE_TEMPLATE VectorizedSubAssign > + Submatrix::subAssign( const DenseMatrix& 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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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_ 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline void Submatrix::subAssign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void Submatrix::subAssign( const SparseMatrix& 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 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::subAssign( const SparseMatrix& 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 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 + : public DenseMatrix< Submatrix, false > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Submatrix This; //!< Type of this Submatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this Submatrix instance. + typedef SubmatrixTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the submatrix elements. + typedef SIMDTrait_ SIMDType; //!< SIMD type of the submatrix elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant submatrix value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Pointer to a constant submatrix value. + typedef const ElementType* ConstPointer; + + //! Pointer to a non-constant submatrix value. + typedef If_< Or< IsConst, Not< HasMutableDataAccess > >, ConstPointer, ElementType* > Pointer; + + //! Iterator over constant elements. + typedef ConstIterator_ ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, Iterator_ > 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 > list ); + inline Submatrix& operator=( const Submatrix& rhs ); + + template< typename MT2, bool SO > + inline Submatrix& operator=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline DisableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline EnableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline DisableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline EnableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline Submatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, Submatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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_ >::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_ >::value && + HasSIMDAdd< ElementType, ElementType_ >::value && + !IsDiagonal::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_ >::value && + HasSIMDSub< ElementType, ElementType_ >::value && + !IsDiagonal::value }; + }; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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* 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* 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 > assign( const DenseMatrix& rhs ); + + template< typename MT2 > + inline EnableIf_< VectorizedAssign > assign( const DenseMatrix& rhs ); + + template< typename MT2 > inline void assign( const DenseMatrix& rhs ); + template< typename MT2 > inline void assign( const SparseMatrix& rhs ); + template< typename MT2 > inline void assign( const SparseMatrix& rhs ); + + template< typename MT2 > + inline DisableIf_< VectorizedAddAssign > addAssign( const DenseMatrix& rhs ); + + template< typename MT2 > + inline EnableIf_< VectorizedAddAssign > addAssign( const DenseMatrix& rhs ); + + template< typename MT2 > inline void addAssign( const DenseMatrix& rhs ); + template< typename MT2 > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT2 > inline void addAssign( const SparseMatrix& rhs ); + + template< typename MT2 > + inline DisableIf_< VectorizedSubAssign > subAssign( const DenseMatrix& rhs ); + + template< typename MT2 > + inline EnableIf_< VectorizedSubAssign > subAssign( const DenseMatrix& rhs ); + + template< typename MT2 > inline void subAssign( const DenseMatrix& rhs ); + template< typename MT2 > inline void subAssign( const SparseMatrix& rhs ); + template< typename MT2 > inline void subAssign( const SparseMatrix& 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 + submatrix( const Submatrix& 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& sm ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Submatrix& a, const Matrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Matrix& a, const Submatrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Submatrix& a, const Submatrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF > + friend bool tryAssign( const Submatrix& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& rhs, + size_t row, size_t column ); + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend DerestrictTrait_< Submatrix > derestrict( Submatrix& 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::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::Reference + Submatrix::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::ConstReference + Submatrix::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( 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::Reference + Submatrix::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::ConstReference + Submatrix::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::Pointer + Submatrix::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::ConstPointer + Submatrix::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::Pointer + Submatrix::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::ConstPointer + Submatrix::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::Iterator + Submatrix::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::ConstIterator + Submatrix::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::ConstIterator + Submatrix::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::Iterator + Submatrix::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::ConstIterator + Submatrix::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::ConstIterator + Submatrix::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& + Submatrix::operator=( const ElementType& rhs ) +{ + const size_t iend( row_ + m_ ); + + for( size_t i=row_; i::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( max( i+1UL, column_ ) ) + :( max( i, column_ ) ) ) + :( column_ ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( min( i, column_+n_ ) ) + :( min( i+1UL, column_+n_ ) ) ) + :( column_+n_ ) ); + + for( size_t j=jbegin; j // Type of the dense matrix +inline Submatrix& + Submatrix::operator=( initializer_list< initializer_list > 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& + Submatrix::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_ 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& + Submatrix::operator=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + typedef If_< IsRestricted, CompositeType_, const MT2& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, row_, column_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + if( IsSparseMatrix::value ) + reset(); + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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, RequiresEvaluation >, Submatrix& > + Submatrix::operator+=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ left( derestrict( *this ) ); + + if( ( ( IsSymmetric::value || IsHermitian::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, RequiresEvaluation >, Submatrix& > + Submatrix::operator+=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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, RequiresEvaluation >, Submatrix& > + Submatrix::operator-=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ left( derestrict( *this ) ); + + if( ( ( IsSymmetric::value || IsHermitian::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, RequiresEvaluation >, Submatrix& > + Submatrix::operator-=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& + Submatrix::operator*=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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_ 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, Submatrix >& + Submatrix::operator*=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + DerestrictTrait_ 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, Submatrix >& + Submatrix::operator/=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + DerestrictTrait_ 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::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::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::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::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::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::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::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::nonZeros() const +{ + const size_t iend( row_ + m_ ); + const size_t jend( column_ + n_ ); + size_t nonzeros( 0UL ); + + for( size_t i=row_; i // Type of the dense matrix +inline size_t Submatrix::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 // Type of the dense matrix +inline void Submatrix::reset() +{ + using blaze::clear; + + for( size_t i=row_; i::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( max( i+1UL, column_ ) ) + :( max( i, column_ ) ) ) + :( column_ ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( min( i, column_+n_ ) ) + :( min( i+1UL, column_+n_ ) ) ) + :( column_+n_ ) ); + + for( size_t j=jbegin; j // Type of the dense matrix +inline void Submatrix::reset( size_t i ) +{ + using blaze::clear; + + BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" ); + + const size_t jbegin( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( max( i+1UL, column_ ) ) + :( max( i, column_ ) ) ) + :( column_ ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( min( i, column_+n_ ) ) + :( min( i+1UL, column_+n_ ) ) ) + :( column_+n_ ) ); + + for( size_t j=jbegin; j // Type of the dense matrix +inline Submatrix& Submatrix::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_ 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& Submatrix::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_ 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& Submatrix::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::value ) + ?( ( IsStrictlyUpper::value ) + ?( max( i+1UL, column_ ) ) + :( max( i, column_ ) ) ) + :( column_ ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsStrictlyLower::value ) + ?( min( i, column_+n_ ) ) + :( min( i+1UL, column_+n_ ) ) ) + :( column_+n_ ) ); + + for( size_t j=jbegin; j // Type of the dense matrix +inline bool Submatrix::hasOverlap() const noexcept +{ + BLAZE_INTERNAL_ASSERT( IsSymmetric::value || IsHermitian::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::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::canAlias( const Submatrix* 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::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::isAliased( const Submatrix* 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::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::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::SIMDType + Submatrix::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::SIMDType + Submatrix::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::SIMDType + Submatrix::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::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::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::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::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::BLAZE_TEMPLATE VectorizedAssign > + Submatrix::assign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline EnableIf_< typename Submatrix::BLAZE_TEMPLATE VectorizedAssign > + Submatrix::assign( const DenseMatrix& 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 right( (~rhs).begin(i) ); + + for( ; j 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline void Submatrix::assign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void Submatrix::assign( const SparseMatrix& 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 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::assign( const SparseMatrix& 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 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::BLAZE_TEMPLATE VectorizedAddAssign > + Submatrix::addAssign( const DenseMatrix& 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::value ) { + matrix_(row_+i,column_+i) += (~rhs)(i,i); + } + else { + for( size_t j=0UL; j // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline EnableIf_< typename Submatrix::BLAZE_TEMPLATE VectorizedAddAssign > + Submatrix::addAssign( const DenseMatrix& 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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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_ 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline void Submatrix::addAssign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void Submatrix::addAssign( const SparseMatrix& 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 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::addAssign( const SparseMatrix& 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 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::BLAZE_TEMPLATE VectorizedSubAssign > + Submatrix::subAssign( const DenseMatrix& 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::value ) { + matrix_(row_+i,column_+i) -= (~rhs)(i,i); + } + else { + for( size_t j=0UL; j // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline EnableIf_< typename Submatrix::BLAZE_TEMPLATE VectorizedSubAssign > + Submatrix::subAssign( const DenseMatrix& 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::value ) + ?( ( IsStrictlyUpper::value ? i+1UL : i ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t jend ( ( IsLower::value ) + ?( IsStrictlyLower::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_ 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline void Submatrix::subAssign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void Submatrix::subAssign( const SparseMatrix& 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 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::subAssign( const SparseMatrix& 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 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 + : public DenseMatrix< Submatrix, true > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Submatrix This; //!< Type of this Submatrix instance. + typedef DenseMatrix BaseType; //!< Base type of this Submatrix instance. + typedef SubmatrixTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the submatrix elements. + typedef SIMDTrait_ SIMDType; //!< SIMD type of the submatrix elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant submatrix value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Pointer to a constant submatrix value. + typedef const ElementType* ConstPointer; + + //! Pointer to a non-constant submatrix value. + typedef If_< Or< IsConst, Not< HasMutableDataAccess > >, ConstPointer, ElementType* > Pointer; + + //! Iterator over constant elements. + typedef ConstIterator_ ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, Iterator_ > 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 > list ); + inline Submatrix& operator=( const Submatrix& rhs ); + + template< typename MT2, bool SO > + inline Submatrix& operator=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline DisableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline EnableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator+=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline DisableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline EnableIf_< And< IsRestricted, RequiresEvaluation >, Submatrix& > + operator-=( const Matrix& rhs ); + + template< typename MT2, bool SO > + inline Submatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, Submatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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_ >::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_ >::value && + HasSIMDAdd< ElementType, ElementType_ >::value && + !IsDiagonal::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_ >::value && + HasSIMDSub< ElementType, ElementType_ >::value && + !IsDiagonal::value }; + }; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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* 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* 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 > assign( const DenseMatrix& rhs ); + + template< typename MT2 > + inline EnableIf_< VectorizedAssign > assign( const DenseMatrix& rhs ); + + template< typename MT2 > inline void assign( const DenseMatrix& rhs ); + template< typename MT2 > inline void assign( const SparseMatrix& rhs ); + template< typename MT2 > inline void assign( const SparseMatrix& rhs ); + + template< typename MT2 > + inline DisableIf_< VectorizedAddAssign > addAssign( const DenseMatrix& rhs ); + + template< typename MT2 > + inline EnableIf_< VectorizedAddAssign > addAssign( const DenseMatrix& rhs ); + + template< typename MT2 > inline void addAssign( const DenseMatrix& rhs ); + template< typename MT2 > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT2 > inline void addAssign( const SparseMatrix& rhs ); + + template< typename MT2 > + inline DisableIf_< VectorizedSubAssign > subAssign( const DenseMatrix& rhs ); + + template< typename MT2 > + inline EnableIf_< VectorizedSubAssign > subAssign( const DenseMatrix& rhs ); + + template< typename MT2 > inline void subAssign( const DenseMatrix& rhs ); + template< typename MT2 > inline void subAssign( const SparseMatrix& rhs ); + template< typename MT2 > inline void subAssign( const SparseMatrix& 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 + submatrix( const Submatrix& 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& sm ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Submatrix& a, const Matrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Matrix& a, const Submatrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Submatrix& a, const Submatrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF > + friend bool tryAssign( const Submatrix& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& rhs, + size_t row, size_t column ); + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend DerestrictTrait_< Submatrix > derestrict( Submatrix& 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::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::Reference + Submatrix::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::ConstReference + Submatrix::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( 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::Reference + Submatrix::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::ConstReference + Submatrix::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::Pointer + Submatrix::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::ConstPointer + Submatrix::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::Pointer + Submatrix::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::ConstPointer + Submatrix::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::Iterator + Submatrix::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::ConstIterator + Submatrix::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::ConstIterator + Submatrix::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::Iterator + Submatrix::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::ConstIterator + Submatrix::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::ConstIterator + Submatrix::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& + Submatrix::operator=( const ElementType& rhs ) +{ + const size_t jend( column_ + n_ ); + + for( size_t j=column_; j::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( max( j+1UL, row_ ) ) + :( max( j, row_ ) ) ) + :( row_ ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( min( j, row_+m_ ) ) + :( min( j+1UL, row_+m_ ) ) ) + :( row_+m_ ) ); + + for( size_t i=ibegin; i // Type of the dense matrix +inline Submatrix& + Submatrix::operator=( initializer_list< initializer_list > 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 // Type of the dense matrix +inline Submatrix& + Submatrix::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_ 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& + Submatrix::operator=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + typedef If_< IsRestricted, CompositeType_, const MT2& > Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, row_, column_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + if( IsSparseMatrix::value ) + reset(); + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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, RequiresEvaluation >, Submatrix& > + Submatrix::operator+=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ left( derestrict( *this ) ); + + if( ( ( IsSymmetric::value || IsHermitian::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, RequiresEvaluation >, Submatrix& > + Submatrix::operator+=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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, RequiresEvaluation >, Submatrix& > + Submatrix::operator-=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ left( derestrict( *this ) ); + + if( ( ( IsSymmetric::value || IsHermitian::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, RequiresEvaluation >, Submatrix& > + Submatrix::operator-=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& + Submatrix::operator*=( const Matrix& rhs ) +{ + BLAZE_CONSTRAINT_MUST_BE_DENSE_MATRIX_TYPE ( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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_ 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, Submatrix >& + Submatrix::operator*=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + DerestrictTrait_ 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, Submatrix >& + Submatrix::operator/=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + DerestrictTrait_ 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::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::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::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::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::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::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::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::nonZeros() const +{ + const size_t iend( row_ + m_ ); + const size_t jend( column_ + n_ ); + size_t nonzeros( 0UL ); + + for( size_t j=column_; j // Type of the dense matrix +inline size_t Submatrix::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 // Type of the dense matrix +inline void Submatrix::reset() +{ + using blaze::clear; + + for( size_t j=column_; j::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( max( j+1UL, row_ ) ) + :( max( j, row_ ) ) ) + :( row_ ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( min( j, row_+m_ ) ) + :( min( j+1UL, row_+m_ ) ) ) + :( row_+m_ ) ); + + for( size_t i=ibegin; i // Type of the dense matrix +inline void Submatrix::reset( size_t j ) +{ + using blaze::clear; + + BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" ); + + const size_t ibegin( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( max( j+1UL, row_ ) ) + :( max( j, row_ ) ) ) + :( row_ ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( min( j, row_+m_ ) ) + :( min( j+1UL, row_+m_ ) ) ) + :( row_+m_ ) ); + + for( size_t i=ibegin; i // Type of the dense matrix +inline Submatrix& Submatrix::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_ 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& Submatrix::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_ 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& Submatrix::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::value ) + ?( ( IsStrictlyLower::value ) + ?( max( j+1UL, row_ ) ) + :( max( j, row_ ) ) ) + :( row_ ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsStrictlyUpper::value ) + ?( min( j, row_+m_ ) ) + :( min( j+1UL, row_+m_ ) ) ) + :( row_+m_ ) ); + + for( size_t i=ibegin; i // Type of the dense matrix +inline bool Submatrix::hasOverlap() const noexcept +{ + BLAZE_INTERNAL_ASSERT( IsSymmetric::value || IsHermitian::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::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::canAlias( const Submatrix* 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::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::isAliased( const Submatrix* 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::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::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::SIMDType + Submatrix::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::SIMDType + Submatrix::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::SIMDType + Submatrix::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::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::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::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::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::BLAZE_TEMPLATE VectorizedAssign > + Submatrix::assign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline EnableIf_< typename Submatrix::BLAZE_TEMPLATE VectorizedAssign > + Submatrix::assign( const DenseMatrix& 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 right( (~rhs).begin(j) ); + + for( ; i 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline void Submatrix::assign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void Submatrix::assign( const SparseMatrix& 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 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::assign( const SparseMatrix& 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 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::BLAZE_TEMPLATE VectorizedAddAssign > + Submatrix::addAssign( const DenseMatrix& 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::value ) { + matrix_(row_+j,column_+j) += (~rhs)(j,j); + } + else { + for( size_t i=0UL; i // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline EnableIf_< typename Submatrix::BLAZE_TEMPLATE VectorizedAddAssign > + Submatrix::addAssign( const DenseMatrix& 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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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_ 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline void Submatrix::addAssign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void Submatrix::addAssign( const SparseMatrix& 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 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::addAssign( const SparseMatrix& 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 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::BLAZE_TEMPLATE VectorizedSubAssign > + Submatrix::subAssign( const DenseMatrix& 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::value ) { + matrix_(row_+j,column_+j) -= (~rhs)(j,j); + } + else { + for( size_t i=0UL; i // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline EnableIf_< typename Submatrix::BLAZE_TEMPLATE VectorizedSubAssign > + Submatrix::subAssign( const DenseMatrix& 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::value ) + ?( ( IsStrictlyLower::value ? j+1UL : j ) & size_t(-SIMDSIZE) ) + :( 0UL ) ); + const size_t iend ( ( IsUpper::value ) + ?( IsStrictlyUpper::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_ 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side dense matrix +inline void Submatrix::subAssign( const DenseMatrix& 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 // Type of the dense matrix +template< typename MT2 > // Type of the right-hand side sparse matrix +inline void Submatrix::subAssign( const SparseMatrix& 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 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::subAssign( const SparseMatrix& 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 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public SparseMatrix< Submatrix, false > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the sparse matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Submatrix This; //!< Type of this Submatrix instance. + typedef SparseMatrix BaseType; //!< Base type of this Submatrix instance. + typedef SubmatrixTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the submatrix elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant submatrix value. + typedef If_< IsConst, ConstReference, Reference_ > 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::value }; + //******************************************************************************************* + + //**Type definitions************************************************************************* + //! Type of the underlying sparse elements. + typedef typename std::iterator_traits::value_type SET; + + typedef Reference_ RT; //!< Reference type of the underlying sparse element. + typedef ConstReference_ CRT; //!< Reference-to-const type of the underlying sparse element. + //******************************************************************************************* + + public: + //**Type definitions************************************************************************* + typedef ValueType_ ValueType; //!< The value type of the row element. + typedef size_t IndexType; //!< The index type of the row element. + typedef IfTrue_ 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 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& 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& 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& 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_ > ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, SubmatrixIterator< MT, Iterator_ > > 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& rhs ); + template< typename MT2, bool SO > inline Submatrix& operator+=( const Matrix& rhs ); + template< typename MT2, bool SO > inline Submatrix& operator-=( const Matrix& rhs ); + template< typename MT2, bool SO > inline Submatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_, Submatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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& rhs ); + template< typename MT2 > inline void assign ( const SparseMatrix& rhs ); + template< typename MT2 > inline void assign ( const SparseMatrix& rhs ); + template< typename MT2, bool SO > inline void addAssign( const DenseMatrix& rhs ); + template< typename MT2, bool SO > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT2, bool SO > inline void subAssign( const DenseMatrix& rhs ); + template< typename MT2, bool SO > inline void subAssign( const SparseMatrix& 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 + submatrix( const Submatrix& 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& sm ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Submatrix& a, const Matrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Matrix& a, const Submatrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Submatrix& a, const Submatrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF > + friend bool tryAssign( const Submatrix& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& rhs, + size_t row, size_t column ); + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend DerestrictTrait_< Submatrix > derestrict( Submatrix& 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::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::Reference + Submatrix::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::ConstReference + Submatrix::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( 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::Reference + Submatrix::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::ConstReference + Submatrix::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::Iterator + Submatrix::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::ConstIterator + Submatrix::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::ConstIterator + Submatrix::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::Iterator + Submatrix::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::ConstIterator + Submatrix::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::ConstIterator + Submatrix::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& + Submatrix::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_ 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& + Submatrix::operator=( const Matrix& rhs ) +{ + using blaze::assign; + + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + typedef CompositeType_ Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, row_, column_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& + Submatrix::operator+=( const Matrix& 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_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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& + Submatrix::operator-=( const Matrix& 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_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& + Submatrix::operator*=( const Matrix& 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_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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_ 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_, Submatrix >& + Submatrix::operator*=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + for( size_t i=0UL; ivalue() *= 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_, Submatrix >& + Submatrix::operator/=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + typedef DivTrait_ DT; + typedef If_< IsNumeric
, DT, Other > Tmp; + + // Depending on the two involved data types, an integer division is applied or a + // floating point division is selected. + if( IsNumeric
::value && IsFloatingPoint
::value ) { + const Tmp tmp( Tmp(1)/static_cast( rhs ) ); + for( size_t i=0UL; ivalue() *= tmp; + } + } + else { + for( size_t i=0UL; ivalue() /= 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::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::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::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::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::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::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::nonZeros() const +{ + size_t nonzeros( 0UL ); + + for( size_t i=0UL; i // Alignment flag +inline size_t Submatrix::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::reset() +{ + for( size_t i=row_; i::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( max( i+1UL, column_ ) ) + :( max( i, column_ ) ) ) + :( column_ ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::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::reset( size_t i ) +{ + BLAZE_USER_ASSERT( i < rows(), "Invalid row access index" ); + + const size_t index( row_ + i ); + + const size_t jbegin( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::value ) + ?( max( i+1UL, column_ ) ) + :( max( i, column_ ) ) ) + :( column_ ) ); + const size_t jend ( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::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::Iterator + Submatrix::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::Iterator + Submatrix::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::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::Iterator + Submatrix::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::Iterator + Submatrix::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::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::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::trim() +{ + for( size_t i=0UL; i // Alignment flag +void Submatrix::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& Submatrix::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_ 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& Submatrix::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_ 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& Submatrix::scale( const Other& scalar ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + for( size_t i=0UL; ivalue() *= 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::hasOverlap() const noexcept +{ + BLAZE_INTERNAL_ASSERT( IsSymmetric::value || IsHermitian::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::Iterator + Submatrix::find( size_t i, size_t j ) +{ + const Iterator_ 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::ConstIterator + Submatrix::find( size_t i, size_t j ) const +{ + const ConstIterator_ 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::Iterator + Submatrix::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::ConstIterator + Submatrix::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::Iterator + Submatrix::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::ConstIterator + Submatrix::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 MatrixType; + typedef blaze::Submatrix 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::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::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::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::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::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::assign( const DenseMatrix& 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::value || IsHermitian::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::assign( const SparseMatrix& 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_ element=(~rhs).begin(i); element!=(~rhs).end(i); ++element ) { + if( IsSymmetric::value || IsHermitian::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::assign( const SparseMatrix& 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_ RhsIterator; + + // Counting the number of elements per row + std::vector rowLengths( m_, 0UL ); + for( size_t j=0UL; jindex()]; + } + + // Resizing the sparse matrix + for( size_t i=0UL; i::value || IsHermitian::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::addAssign( const DenseMatrix& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::addAssign( const SparseMatrix& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::subAssign( const DenseMatrix& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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::subAssign( const SparseMatrix& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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 + : public SparseMatrix< Submatrix, true > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the sparse matrix expression. + typedef If_< IsExpression, MT, MT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Submatrix This; //!< Type of this Submatrix instance. + typedef SparseMatrix BaseType; //!< Base type of this Submatrix instance. + typedef SubmatrixTrait_ ResultType; //!< Result type for expression template evaluations. + typedef OppositeType_ OppositeType; //!< Result type with opposite storage order for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the submatrix elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant submatrix value. + typedef If_< IsConst, ConstReference, Reference_ > 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::value }; + //******************************************************************************************* + + //**Type definitions************************************************************************* + //! Type of the underlying sparse elements. + typedef typename std::iterator_traits::value_type SET; + + typedef Reference_ RT; //!< Reference type of the underlying sparse element. + typedef ConstReference_ CRT; //!< Reference-to-const type of the underlying sparse element. + //******************************************************************************************* + + public: + //**Type definitions************************************************************************* + typedef ValueType_ ValueType; //!< The value type of the row element. + typedef size_t IndexType; //!< The index type of the row element. + typedef IfTrue_ 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 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& 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& 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& 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_ > ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, SubmatrixIterator< MT, Iterator_ > > 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& rhs ); + template< typename MT2, bool SO > inline Submatrix& operator+=( const Matrix& rhs ); + template< typename MT2, bool SO > inline Submatrix& operator-=( const Matrix& rhs ); + template< typename MT2, bool SO > inline Submatrix& operator*=( const Matrix& rhs ); + + template< typename Other > + inline EnableIf_, Submatrix >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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& rhs ); + template< typename MT2 > inline void assign ( const SparseMatrix& rhs ); + template< typename MT2 > inline void assign ( const SparseMatrix& rhs ); + template< typename MT2, bool SO > inline void addAssign( const DenseMatrix& rhs ); + template< typename MT2, bool SO > inline void addAssign( const SparseMatrix& rhs ); + template< typename MT2, bool SO > inline void subAssign( const DenseMatrix& rhs ); + template< typename MT2, bool SO > inline void subAssign( const SparseMatrix& 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 + submatrix( const Submatrix& 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& sm ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Submatrix& a, const Matrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Matrix& a, const Submatrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend bool isSame( const Submatrix& a, const Submatrix& b ) noexcept; + + template< typename MT2, bool AF2, bool SO2, bool DF2, typename VT, bool TF > + friend bool tryAssign( const Submatrix& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& 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& lhs, const Matrix& 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& lhs, const Vector& rhs, + size_t row, size_t column ); + + template< typename MT2, bool AF2, bool SO2, bool DF2 > + friend DerestrictTrait_< Submatrix > derestrict( Submatrix& 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::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::Reference + Submatrix::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::ConstReference + Submatrix::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( 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::Reference + Submatrix::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::ConstReference + Submatrix::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::Iterator + Submatrix::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::ConstIterator + Submatrix::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::ConstIterator + Submatrix::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::Iterator + Submatrix::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::ConstIterator + Submatrix::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::ConstIterator + Submatrix::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& + Submatrix::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_ 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& + Submatrix::operator=( const Matrix& rhs ) +{ + using blaze::assign; + + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + if( rows() != (~rhs).rows() || columns() != (~rhs).columns() ) { + BLAZE_THROW_INVALID_ARGUMENT( "Matrix sizes do not match" ); + } + + typedef CompositeType_ Right; + Right right( ~rhs ); + + if( !tryAssign( matrix_, right, row_, column_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted matrix" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &matrix_ ) ) { + const ResultType_ 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& + Submatrix::operator+=( const Matrix& 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_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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& + Submatrix::operator-=( const Matrix& 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_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& + Submatrix::operator*=( const Matrix& 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_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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_ 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_, Submatrix >& + Submatrix::operator*=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + for( size_t i=0UL; ivalue() *= 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_, Submatrix >& + Submatrix::operator/=( Other rhs ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + typedef DivTrait_ DT; + typedef If_< IsNumeric
, DT, Other > Tmp; + + // Depending on the two involved data types, an integer division is applied or a + // floating point division is selected. + if( IsNumeric
::value && IsFloatingPoint
::value ) { + const Tmp tmp( Tmp(1)/static_cast( rhs ) ); + for( size_t i=0UL; ivalue() *= tmp; + } + } + else { + for( size_t i=0UL; ivalue() /= 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::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::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::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::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::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::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::nonZeros() const +{ + size_t nonzeros( 0UL ); + + for( size_t i=0UL; i // Alignment flag +inline size_t Submatrix::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::reset() +{ + for( size_t j=column_; j::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( max( j+1UL, row_ ) ) + :( max( j, row_ ) ) ) + :( row_ ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::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::reset( size_t j ) +{ + BLAZE_USER_ASSERT( j < columns(), "Invalid column access index" ); + + const size_t index( column_ + j ); + + const size_t ibegin( ( IsLower::value ) + ?( ( IsUniLower::value || IsStrictlyLower::value ) + ?( max( j+1UL, row_ ) ) + :( max( j, row_ ) ) ) + :( row_ ) ); + const size_t iend ( ( IsUpper::value ) + ?( ( IsUniUpper::value || IsStrictlyUpper::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::Iterator + Submatrix::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::Iterator + Submatrix::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::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::Iterator + Submatrix::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::Iterator + Submatrix::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::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::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::trim() +{ + for( size_t j=0UL; j // Alignment flag +void Submatrix::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& Submatrix::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_ 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& Submatrix::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_ 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& Submatrix::scale( const Other& scalar ) +{ + BLAZE_CONSTRAINT_MUST_NOT_BE_UNITRIANGULAR_MATRIX_TYPE( MT ); + + for( size_t i=0UL; ivalue() *= 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::hasOverlap() const noexcept +{ + BLAZE_INTERNAL_ASSERT( IsSymmetric::value || IsHermitian::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::Iterator + Submatrix::find( size_t i, size_t j ) +{ + const Iterator_ 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::ConstIterator + Submatrix::find( size_t i, size_t j ) const +{ + const ConstIterator_ 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::Iterator + Submatrix::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::ConstIterator + Submatrix::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::Iterator + Submatrix::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::ConstIterator + Submatrix::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 MatrixType; + typedef blaze::Submatrix 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::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::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::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::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::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::assign( const DenseMatrix& 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::value || IsHermitian::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::assign( const SparseMatrix& 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_ element=(~rhs).begin(j); element!=(~rhs).end(j); ++element ) { + if( IsSymmetric::value || IsHermitian::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::assign( const SparseMatrix& 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_ RhsIterator; + + // Counting the number of elements per column + std::vector columnLengths( n_, 0UL ); + for( size_t i=0UL; iindex()]; + } + + // Resizing the sparse matrix + for( size_t j=0UL; j::value || IsHermitian::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::addAssign( const DenseMatrix& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::addAssign( const SparseMatrix& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::subAssign( const DenseMatrix& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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::subAssign( const SparseMatrix& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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 +#include +#include + + +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; + + 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 sv = subvector( x, 8UL, 16UL ); + \endcode + + \code + using SparseVectorType = blaze::CompressedVector; + + 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 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; + using SparseVectorType = blaze::CompressedVector; + using DenseMatrixType = blaze::DynamicMatrix; + + 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 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; + VectorType v; + // ... Resizing and initialization + + // Creating an 8-dimensional subvector, starting from index 4 + blaze::Subvector 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; + using SubvectorType = blaze::Subvector; + + 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; + using SubvectorType = blaze::Subvector; + + 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; + VectorType v( 256UL ); // Non-initialized vector of size 256 + + using SubvectorType = blaze::Subvector; + 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; + using SubvectorType = blaze::Subvector; + + 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; + using SparseVectorType = blaze::CompressedVector; + DenseVectorType d1, d2, d3; + SparseVectorType s1, s2; + + // ... Resizing and initialization + + using DenseMatrixType = blaze::DynamicMatrix; + DenseMatrixType A; + + using SubvectorType = blaze::Subvector; + 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; + + DenseVectorType x; + // ... Resizing and initialization + + // Identical creations of an unaligned subvector in the range [8..23] + blaze::Subvector sv1 = subvector ( x, 8UL, 16UL ); + blaze::Subvector sv2 = subvector( x, 8UL, 16UL ); + blaze::Subvector sv3 = subvector ( x, 8UL, 16UL ); + blaze::Subvector sv4 = subvector( 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 sv = subvector( 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; + using SubvectorType = blaze::Subvector; + + VectorType d( 17UL ); + // ... Resizing and initialization + + // OK: Starts at the beginning and the size is a multiple of 4 + SubvectorType dsv1 = subvector( d, 0UL, 12UL ); + + // OK: Start index and the size are both a multiple of 4 + SubvectorType dsv2 = subvector( d, 4UL, 8UL ); + + // OK: The start index is a multiple of 4 and the subvector includes the last element + SubvectorType dsv3 = subvector( d, 8UL, 9UL ); + + // Error: Start index is not a multiple of 4 + SubvectorType dsv4 = subvector( d, 5UL, 8UL ); + + // Error: Size is not a multiple of 4 and the subvector does not include the last element + SubvectorType dsv5 = subvector( 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; + + SparseVectorType x; + // ... Resizing and initialization + + // Creating an aligned subvector in the range [8..23] + blaze::SparseSubvector sv = subvector( 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; + using SubvectorType = blaze::Subvector; + + 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::value // Transpose flag + , bool DF = IsDenseVector::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public DenseVector< Subvector, TF > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense vector expression. + typedef If_< IsExpression, VT, VT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Subvector This; //!< Type of this Subvector instance. + typedef DenseVector BaseType; //!< Base type of this Subvector instance. + typedef SubvectorTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the subvector elements. + typedef SIMDTrait_ SIMDType; //!< SIMD type of the subvector elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant subvector value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Pointer to a constant subvector value. + typedef const ElementType* ConstPointer; + + //! Pointer to a non-constant subvector value. + typedef If_< Or< IsConst, Not< HasMutableDataAccess > >, 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::iterator_category IteratorCategory; + + //! Type of the underlying elements. + typedef typename std::iterator_traits::value_type ValueType; + + //! Pointer return type. + typedef typename std::iterator_traits::pointer PointerType; + + //! Reference return type. + typedef typename std::iterator_traits::reference ReferenceType; + + //! Difference between two iterators. + typedef typename std::iterator_traits::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& 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_ > ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, SubvectorIterator< Iterator_ > > 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 list ); + inline Subvector& operator= ( const Subvector& rhs ); + template< typename VT2 > inline Subvector& operator= ( const Vector& rhs ); + template< typename VT2 > inline Subvector& operator+=( const Vector& rhs ); + template< typename VT2 > inline Subvector& operator-=( const Vector& rhs ); + template< typename VT2 > inline Subvector& operator*=( const DenseVector& rhs ); + template< typename VT2 > inline Subvector& operator*=( const SparseVector& rhs ); + template< typename VT2 > inline Subvector& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, Subvector >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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_ >::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_ >::value && + HasSIMDAdd< ElementType, ElementType_ >::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_ >::value && + HasSIMDSub< ElementType, ElementType_ >::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_ >::value && + HasSIMDMult< ElementType, ElementType_ >::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_ >::value && + HasSIMDDiv< ElementType, ElementType_ >::value }; + }; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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* 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* 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 > assign( const DenseVector & rhs ); + + template< typename VT2 > + inline EnableIf_< VectorizedAssign > assign( const DenseVector & rhs ); + + template< typename VT2 > inline void assign( const SparseVector& rhs ); + + template< typename VT2 > + inline DisableIf_< VectorizedAddAssign > addAssign( const DenseVector & rhs ); + + template< typename VT2 > + inline EnableIf_< VectorizedAddAssign > addAssign ( const DenseVector & rhs ); + + template< typename VT2 > inline void addAssign( const SparseVector& rhs ); + + template< typename VT2 > + inline DisableIf_< VectorizedSubAssign > subAssign ( const DenseVector & rhs ); + + template< typename VT2 > + inline EnableIf_< VectorizedSubAssign > subAssign( const DenseVector & rhs ); + + template< typename VT2 > inline void subAssign( const SparseVector& rhs ); + + template< typename VT2 > + inline DisableIf_< VectorizedMultAssign > multAssign( const DenseVector & rhs ); + + template< typename VT2 > + inline EnableIf_< VectorizedMultAssign > multAssign( const DenseVector & rhs ); + + template< typename VT2 > inline void multAssign( const SparseVector& rhs ); + + template< typename VT2 > + inline DisableIf_< VectorizedDivAssign > divAssign( const DenseVector & rhs ); + + template< typename VT2 > + inline EnableIf_< VectorizedDivAssign > divAssign( const DenseVector & 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 + subvector( const Subvector& sv, size_t index, size_t size ); + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend bool isIntact( const Subvector& sv ) noexcept; + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend bool isSame( const Subvector& a, const Vector& b ) noexcept; + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend bool isSame( const Vector& a, const Subvector& b ) noexcept; + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend bool isSame( const Subvector& a, const Subvector& b ) noexcept; + + template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 > + friend bool tryAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 > + friend bool tryAddAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 > + friend bool trySubAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 > + friend bool tryMultAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend DerestrictTrait_< Subvector > derestrict( Subvector& 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::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::Reference + Subvector::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::ConstReference + Subvector::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid subvector access index" ); + return const_cast( 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::Reference + Subvector::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::ConstReference + Subvector::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::Pointer + Subvector::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::ConstPointer + Subvector::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::Iterator + Subvector::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::ConstIterator + Subvector::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::ConstIterator + Subvector::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::Iterator + Subvector::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::ConstIterator + Subvector::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::ConstIterator + Subvector::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& + Subvector::operator=( const ElementType& rhs ) +{ + const size_t iend( offset_ + size_ ); + + for( size_t i=offset_; i // Transpose flag +inline Subvector& + Subvector::operator=( initializer_list 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& + Subvector::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_ 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& + Subvector::operator=( const Vector& 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" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT2& > Right; + Right right( ~rhs ); + + if( !tryAssign( vector_, right, offset_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &vector_ ) ) { + const ResultType_ tmp( right ); + smpAssign( left, tmp ); + } + else { + if( IsSparseVector::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& + Subvector::operator+=( const Vector& 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" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT2& > Right; + Right right( ~rhs ); + + if( !tryAddAssign( vector_, right, offset_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &vector_ ) ) { + const ResultType_ 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& + Subvector::operator-=( const Vector& 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" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT2& > Right; + Right right( ~rhs ); + + if( !trySubAssign( vector_, right, offset_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &vector_ ) ) { + const ResultType_ 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& + Subvector::operator*=( const DenseVector& 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" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT2& > Right; + Right right( ~rhs ); + + if( !tryMultAssign( vector_, right, offset_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &vector_ ) ) { + const ResultType_ 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& + Subvector::operator*=( const SparseVector& 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_ 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& + Subvector::operator/=( const DenseVector& 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" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT2& > Right; + Right right( ~rhs ); + + if( !tryDivAssign( vector_, right, offset_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &vector_ ) ) { + const ResultType_ 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, Subvector >& + Subvector::operator*=( Other rhs ) +{ + DerestrictTrait_ 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, Subvector >& + Subvector::operator/=( Other rhs ) +{ + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + DerestrictTrait_ 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::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::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::nonZeros() const +{ + size_t nonzeros( 0 ); + + const size_t iend( offset_ + size_ ); + for( size_t i=offset_; i // Transpose flag +inline void Subvector::reset() +{ + using blaze::clear; + + const size_t iend( offset_ + size_ ); + for( size_t i=offset_; i // Transpose flag +template< typename Other > // Data type of the scalar value +inline Subvector& + Subvector::scale( const Other& scalar ) +{ + const size_t iend( offset_ + size_ ); + for( size_t i=offset_; i // Transpose flag +template< typename Other > // Data type of the foreign expression +inline bool Subvector::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::canAlias( const Subvector* 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::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::isAliased( const Subvector* 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::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::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::SIMDType + Subvector::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::SIMDType + Subvector::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::SIMDType + Subvector::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::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::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::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::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::BLAZE_TEMPLATE VectorizedAssign > + Subvector::assign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const size_t ipos( size() & size_t(-2) ); + for( size_t i=0UL; i // Transpose flag +template< typename VT2 > // Type of the right-hand side dense vector +inline EnableIf_< typename Subvector::BLAZE_TEMPLATE VectorizedAssign > + Subvector::assign( const DenseVector& 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_ right( (~rhs).begin() ); + + if( useStreaming && isAligned_ && + ( size_ > ( cacheSize/( sizeof(ElementType) * 3UL ) ) ) && + !(~rhs).isAliased( &vector_ ) ) + { + for( ; i // Transpose flag +template< typename VT2 > // Type of the right-hand side sparse vector +inline void Subvector::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedAddAssign > + Subvector::addAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const size_t ipos( size() & size_t(-2) ); + for( size_t i=0UL; i // Transpose flag +template< typename VT2 > // Type of the right-hand side dense vector +inline EnableIf_< typename Subvector::BLAZE_TEMPLATE VectorizedAddAssign > + Subvector::addAssign( const DenseVector& 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_ 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 // Transpose flag +template< typename VT2 > // Type of the right-hand side sparse vector +inline void Subvector::addAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedSubAssign > + Subvector::subAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const size_t ipos( size() & size_t(-2) ); + for( size_t i=0UL; i // Transpose flag +template< typename VT2 > // Type of the right-hand side dense vector +inline EnableIf_< typename Subvector::BLAZE_TEMPLATE VectorizedSubAssign > + Subvector::subAssign( const DenseVector& 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_ 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 // Transpose flag +template< typename VT2 > // Type of the right-hand side sparse vector +inline void Subvector::subAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedMultAssign > + Subvector::multAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const size_t ipos( size() & size_t(-2) ); + for( size_t i=0UL; i // Transpose flag +template< typename VT2 > // Type of the right-hand side dense vector +inline EnableIf_< typename Subvector::BLAZE_TEMPLATE VectorizedMultAssign > + Subvector::multAssign( const DenseVector& 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_ 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 // Transpose flag +template< typename VT2 > // Type of the right-hand side sparse vector +inline void Subvector::multAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const ResultType tmp( serial( *this ) ); + + reset(); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedDivAssign > + Subvector::divAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const size_t ipos( size() & size_t(-2) ); + for( size_t i=0UL; i // Transpose flag +template< typename VT2 > // Type of the right-hand side dense vector +inline EnableIf_< typename Subvector::BLAZE_TEMPLATE VectorizedDivAssign > + Subvector::divAssign( const DenseVector& 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_ 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 // Transpose flag +class Subvector + : public DenseVector< Subvector, TF > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the dense vector expression. + typedef If_< IsExpression, VT, VT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Subvector This; //!< Type of this Subvector instance. + typedef DenseVector BaseType; //!< Base type of this Subvector instance. + typedef SubvectorTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the subvector elements. + typedef SIMDTrait_ SIMDType; //!< SIMD type of the subvector elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant subvector value. + typedef If_< IsConst, ConstReference, Reference_ > Reference; + + //! Pointer to a constant subvector value. + typedef const ElementType* ConstPointer; + + //! Pointer to a non-constant subvector value. + typedef If_< Or< IsConst, Not< HasMutableDataAccess > >, ConstPointer, ElementType* > Pointer; + + //! Iterator over constant elements. + typedef ConstIterator_ ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, Iterator_ > 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 list ); + inline Subvector& operator= ( const Subvector& rhs ); + template< typename VT2 > inline Subvector& operator= ( const Vector& rhs ); + template< typename VT2 > inline Subvector& operator+=( const Vector& rhs ); + template< typename VT2 > inline Subvector& operator-=( const Vector& rhs ); + template< typename VT2 > inline Subvector& operator*=( const DenseVector& rhs ); + template< typename VT2 > inline Subvector& operator*=( const SparseVector& rhs ); + template< typename VT2 > inline Subvector& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, Subvector >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_< IsNumeric, 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_ >::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_ >::value && + HasSIMDAdd< ElementType, ElementType_ >::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_ >::value && + HasSIMDSub< ElementType, ElementType_ >::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_ >::value && + HasSIMDMult< ElementType, ElementType_ >::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_ >::value && + HasSIMDDiv< ElementType, ElementType_ >::value }; + }; + //********************************************************************************************** + + //**SIMD properties***************************************************************************** + //! The number of elements packed within a single SIMD element. + enum : size_t { SIMDSIZE = SIMDTrait::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* 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* 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 > assign( const DenseVector & rhs ); + + template< typename VT2 > + inline EnableIf_< VectorizedAssign > assign( const DenseVector & rhs ); + + template< typename VT2 > inline void assign( const SparseVector& rhs ); + + template< typename VT2 > + inline DisableIf_< VectorizedAddAssign > addAssign( const DenseVector & rhs ); + + template< typename VT2 > + inline EnableIf_< VectorizedAddAssign > addAssign ( const DenseVector & rhs ); + + template< typename VT2 > inline void addAssign( const SparseVector& rhs ); + + template< typename VT2 > + inline DisableIf_< VectorizedSubAssign > subAssign ( const DenseVector & rhs ); + + template< typename VT2 > + inline EnableIf_< VectorizedSubAssign > subAssign( const DenseVector & rhs ); + + template< typename VT2 > inline void subAssign( const SparseVector& rhs ); + + template< typename VT2 > + inline DisableIf_< VectorizedMultAssign > multAssign( const DenseVector & rhs ); + + template< typename VT2 > + inline EnableIf_< VectorizedMultAssign > multAssign( const DenseVector & rhs ); + + template< typename VT2 > inline void multAssign( const SparseVector& rhs ); + + template< typename VT2 > + inline DisableIf_< VectorizedDivAssign > divAssign( const DenseVector & rhs ); + + template< typename VT2 > + inline EnableIf_< VectorizedDivAssign > divAssign( const DenseVector & 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 + subvector( const Subvector& sv, size_t index, size_t size ); + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend bool isIntact( const Subvector& sv ) noexcept; + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend bool isSame( const Subvector& a, const Vector& b ) noexcept; + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend bool isSame( const Vector& a, const Subvector& b ) noexcept; + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend bool isSame( const Subvector& a, const Subvector& b ) noexcept; + + template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 > + friend bool tryAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 > + friend bool tryAddAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 > + friend bool trySubAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 > + friend bool tryMultAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend DerestrictTrait_< Subvector > derestrict( Subvector& 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::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::Reference + Subvector::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::ConstReference + Subvector::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid subvector access index" ); + return const_cast( 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::Reference + Subvector::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::ConstReference + Subvector::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::Pointer Subvector::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::ConstPointer + Subvector::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::Iterator Subvector::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::ConstIterator + Subvector::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::ConstIterator + Subvector::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::Iterator Subvector::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::ConstIterator + Subvector::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::ConstIterator + Subvector::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& + Subvector::operator=( const ElementType& rhs ) +{ + const size_t iend( offset_ + size_ ); + + for( size_t i=offset_; i // Transpose flag +inline Subvector& + Subvector::operator=( initializer_list 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& + Subvector::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_ 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& + Subvector::operator=( const Vector& 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" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT2& > Right; + Right right( ~rhs ); + + if( !tryAssign( vector_, right, offset_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &vector_ ) ) { + const ResultType_ tmp( right ); + smpAssign( left, tmp ); + } + else { + if( IsSparseVector::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& + Subvector::operator+=( const Vector& 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" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT2& > Right; + Right right( ~rhs ); + + if( !tryAddAssign( vector_, right, offset_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &vector_ ) ) { + const ResultType_ 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& + Subvector::operator-=( const Vector& 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" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT2& > Right; + Right right( ~rhs ); + + if( !trySubAssign( vector_, right, offset_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &vector_ ) ) { + const ResultType_ 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& + Subvector::operator*=( const DenseVector& 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" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT2& > Right; + Right right( ~rhs ); + + if( !tryMultAssign( vector_, right, offset_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &vector_ ) ) { + const ResultType_ 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& + Subvector::operator*=( const SparseVector& 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_ 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& + Subvector::operator/=( const DenseVector& 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" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT2& > Right; + Right right( ~rhs ); + + if( !tryDivAssign( vector_, right, offset_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value && right.canAlias( &vector_ ) ) { + const ResultType_ 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, Subvector >& + Subvector::operator*=( Other rhs ) +{ + DerestrictTrait_ 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, Subvector >& + Subvector::operator/=( Other rhs ) +{ + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + DerestrictTrait_ 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::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::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::nonZeros() const +{ + size_t nonzeros( 0 ); + + const size_t iend( offset_ + size_ ); + for( size_t i=offset_; i // Transpose flag +inline void Subvector::reset() +{ + using blaze::clear; + + const size_t iend( offset_ + size_ ); + for( size_t i=offset_; i // Transpose flag +template< typename Other > // Data type of the scalar value +inline Subvector& Subvector::scale( const Other& scalar ) +{ + const size_t iend( offset_ + size_ ); + for( size_t i=offset_; i // Transpose flag +template< typename Other > // Data type of the foreign expression +inline bool Subvector::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::canAlias( const Subvector* 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::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::isAliased( const Subvector* 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::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::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::SIMDType + Subvector::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::SIMDType + Subvector::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::SIMDType + Subvector::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::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::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::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::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::BLAZE_TEMPLATE VectorizedAssign > + Subvector::assign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const size_t ipos( size() & size_t(-2) ); + for( size_t i=0UL; i // Transpose flag +template< typename VT2 > // Type of the right-hand side dense vector +inline EnableIf_< typename Subvector::BLAZE_TEMPLATE VectorizedAssign > + Subvector::assign( const DenseVector& 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_ right( (~rhs).begin() ); + + if( useStreaming && size_ > ( cacheSize/( sizeof(ElementType) * 3UL ) ) && !(~rhs).isAliased( &vector_ ) ) + { + for( ; i // Transpose flag +template< typename VT2 > // Type of the right-hand side sparse vector +inline void Subvector::assign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedAddAssign > + Subvector::addAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const size_t ipos( size() & size_t(-2) ); + for( size_t i=0UL; i // Transpose flag +template< typename VT2 > // Type of the right-hand side dense vector +inline EnableIf_< typename Subvector::BLAZE_TEMPLATE VectorizedAddAssign > + Subvector::addAssign( const DenseVector& 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_ 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 // Transpose flag +template< typename VT2 > // Type of the right-hand side sparse vector +inline void Subvector::addAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedSubAssign > + Subvector::subAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const size_t ipos( size() & size_t(-2) ); + for( size_t i=0UL; i // Transpose flag +template< typename VT2 > // Type of the right-hand side dense vector +inline EnableIf_< typename Subvector::BLAZE_TEMPLATE VectorizedSubAssign > + Subvector::subAssign( const DenseVector& 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_ 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 // Transpose flag +template< typename VT2 > // Type of the right-hand side sparse vector +inline void Subvector::subAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedMultAssign > + Subvector::multAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const size_t ipos( size() & size_t(-2) ); + for( size_t i=0UL; i // Transpose flag +template< typename VT2 > // Type of the right-hand side dense vector +inline EnableIf_< typename Subvector::BLAZE_TEMPLATE VectorizedMultAssign > + Subvector::multAssign( const DenseVector& 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_ 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 // Transpose flag +template< typename VT2 > // Type of the right-hand side sparse vector +inline void Subvector::multAssign( const SparseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const ResultType tmp( serial( *this ) ); + + reset(); + + for( ConstIterator_ 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::BLAZE_TEMPLATE VectorizedDivAssign > + Subvector::divAssign( const DenseVector& rhs ) +{ + BLAZE_INTERNAL_ASSERT( size() == (~rhs).size(), "Invalid vector sizes" ); + + const size_t ipos( size() & size_t(-2) ); + for( size_t i=0UL; i // Transpose flag +template< typename VT2 > // Type of the right-hand side dense vector +inline EnableIf_< typename Subvector::BLAZE_TEMPLATE VectorizedDivAssign > + Subvector::divAssign( const DenseVector& 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_ 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 // Transpose flag +class Subvector< DVecDVecCrossExpr, unaligned, TF, true > + : public DenseVector< Subvector< DVecDVecCrossExpr, unaligned, TF, true >, TF > + , private View +{ + private: + //**Type definitions**************************************************************************** + typedef DVecDVecCrossExpr CPE; //!< Type of the cross product expression. + typedef ResultType_ RT; //!< Result type of the cross product expression. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Subvector This; //!< Type of this Subvector instance. + typedef DenseVector BaseType; //!< Base type of this Subvector instance. + typedef SubvectorTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the subvector elements. + typedef ReturnType_ 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 + subvector( const Subvector& sv, size_t index, size_t size ); + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isIntact( const Subvector& sv ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isSame( const Subvector& a, const Vector& b ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isSame( const Vector& a, const Subvector& b ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isSame( const Subvector& a, const Subvector& b ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool tryAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool tryAddAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool trySubAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool tryMultAssign( const Subvector& lhs, const Vector& 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, unaligned, TF, true > + : public DenseVector< Subvector< DVecSVecCrossExpr, unaligned, TF, true >, TF > + , private View +{ + private: + //**Type definitions**************************************************************************** + typedef DVecSVecCrossExpr CPE; //!< Type of the cross product expression. + typedef ResultType_ RT; //!< Result type of the cross product expression. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Subvector This; //!< Type of this Subvector instance. + typedef DenseVector BaseType; //!< Base type of this Subvector instance. + typedef SubvectorTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the subvector elements. + typedef ReturnType_ 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 + subvector( const Subvector& sv, size_t index, size_t size ); + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isIntact( const Subvector& sv ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isSame( const Subvector& a, const Vector& b ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isSame( const Vector& a, const Subvector& b ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isSame( const Subvector& a, const Subvector& b ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool tryAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool tryAddAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool trySubAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool tryMultAssign( const Subvector& lhs, const Vector& 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, unaligned, TF, true > + : public DenseVector< Subvector< SVecDVecCrossExpr, unaligned, TF, true >, TF > + , private View +{ + private: + //**Type definitions**************************************************************************** + typedef SVecDVecCrossExpr CPE; //!< Type of the cross product expression. + typedef ResultType_ RT; //!< Result type of the cross product expression. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Subvector This; //!< Type of this Subvector instance. + typedef DenseVector BaseType; //!< Base type of this Subvector instance. + typedef SubvectorTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the subvector elements. + typedef ReturnType_ 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 + subvector( const Subvector& sv, size_t index, size_t size ); + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isIntact( const Subvector& sv ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isSame( const Subvector& a, const Vector& b ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isSame( const Vector& a, const Subvector& b ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isSame( const Subvector& a, const Subvector& b ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool tryAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool tryAddAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool trySubAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool tryMultAssign( const Subvector& lhs, const Vector& 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, unaligned, TF, true > + : public DenseVector< Subvector< SVecSVecCrossExpr, unaligned, TF, true >, TF > + , private View +{ + private: + //**Type definitions**************************************************************************** + typedef SVecSVecCrossExpr CPE; //!< Type of the cross product expression. + typedef ResultType_ RT; //!< Result type of the cross product expression. + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Subvector This; //!< Type of this Subvector instance. + typedef DenseVector BaseType; //!< Base type of this Subvector instance. + typedef SubvectorTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the subvector elements. + typedef ReturnType_ 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 + subvector( const Subvector& sv, size_t index, size_t size ); + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isIntact( const Subvector& sv ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isSame( const Subvector& a, const Vector& b ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isSame( const Vector& a, const Subvector& b ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2 > + friend bool isSame( const Subvector& a, const Subvector& b ) noexcept; + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool tryAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool tryAddAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool trySubAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT3, bool AF, bool TF2, bool DF2, typename VT4 > + friend bool tryMultAssign( const Subvector& lhs, const Vector& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 + : public SparseVector< Subvector, TF > + , private View +{ + private: + //**Type definitions**************************************************************************** + //! Composite data type of the sparse vector expression. + typedef If_< IsExpression, VT, VT& > Operand; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef Subvector This; //!< Type of this Subvector instance. + typedef SparseVector BaseType; //!< Base type of this Subvector instance. + typedef SubvectorTrait_ ResultType; //!< Result type for expression template evaluations. + typedef TransposeType_ TransposeType; //!< Transpose type for expression template evaluations. + typedef ElementType_ ElementType; //!< Type of the subvector elements. + typedef ReturnType_ 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_ ConstReference; + + //! Reference to a non-constant subvector value. + typedef If_< IsConst, ConstReference, Reference_ > 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::value }; + //******************************************************************************************* + + //**Type definitions************************************************************************* + //! Type of the underlying sparse elements. + typedef typename std::iterator_traits::value_type SET; + + typedef Reference_ RT; //!< Reference type of the underlying sparse element. + typedef ConstReference_ CRT; //!< Reference-to-const type of the underlying sparse element. + //******************************************************************************************* + + public: + //**Type definitions************************************************************************* + typedef ValueType_ ValueType; //!< The value type of the row element. + typedef size_t IndexType; //!< The index type of the row element. + typedef IfTrue_ 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 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& 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& 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& 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_ > ConstIterator; + + //! Iterator over non-constant elements. + typedef If_< IsConst, ConstIterator, SubvectorIterator< VT, Iterator_ > > 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& rhs ); + template< typename VT2 > inline Subvector& operator+=( const Vector& rhs ); + template< typename VT2 > inline Subvector& operator-=( const Vector& rhs ); + template< typename VT2 > inline Subvector& operator*=( const Vector& rhs ); + template< typename VT2 > inline Subvector& operator/=( const DenseVector& rhs ); + + template< typename Other > + inline EnableIf_, Subvector >& operator*=( Other rhs ); + + template< typename Other > + inline EnableIf_, 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 & rhs ); + template< typename VT2 > inline void assign ( const SparseVector& rhs ); + template< typename VT2 > inline void addAssign( const DenseVector & rhs ); + template< typename VT2 > inline void addAssign( const SparseVector& rhs ); + template< typename VT2 > inline void subAssign( const DenseVector & rhs ); + template< typename VT2 > inline void subAssign( const SparseVector& 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 + subvector( const Subvector& sv, size_t index, size_t size ); + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend bool isIntact( const Subvector& sv ) noexcept; + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend bool isSame( const Subvector& a, const Vector& b ) noexcept; + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend bool isSame( const Vector& a, const Subvector& b ) noexcept; + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend bool isSame( const Subvector& a, const Subvector& b ) noexcept; + + template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 > + friend bool tryAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 > + friend bool tryAddAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 > + friend bool trySubAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT2, bool AF2, bool TF2, bool DF2, typename VT3 > + friend bool tryMultAssign( const Subvector& lhs, const Vector& rhs, size_t index ); + + template< typename VT2, bool AF2, bool TF2, bool DF2 > + friend DerestrictTrait_< Subvector > derestrict( Subvector& 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::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::Reference + Subvector::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::ConstReference + Subvector::operator[]( size_t index ) const +{ + BLAZE_USER_ASSERT( index < size(), "Invalid subvector access index" ); + return const_cast( 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::Reference + Subvector::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::ConstReference + Subvector::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::Iterator Subvector::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::ConstIterator Subvector::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::ConstIterator Subvector::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::Iterator Subvector::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::ConstIterator Subvector::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::ConstIterator Subvector::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& + Subvector::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_ 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& + Subvector::operator=( const Vector& rhs ) +{ + using blaze::assign; + + 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" ); + } + + typedef If_< IsRestricted, CompositeType_, const VT2& > Right; + Right right( ~rhs ); + + if( !tryAssign( vector_, right, offset_ ) ) { + BLAZE_THROW_INVALID_ARGUMENT( "Invalid assignment to restricted vector" ); + } + + DerestrictTrait_ left( derestrict( *this ) ); + + if( IsReference::value || right.canAlias( &vector_ ) ) { + const ResultType_ 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& + Subvector::operator+=( const Vector& 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_ ); + + typedef AddTrait_< ResultType, ResultType_ > 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_ 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& + Subvector::operator-=( const Vector& 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_ ); + + typedef SubTrait_< ResultType, ResultType_ > 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_ 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& + Subvector::operator*=( const Vector& 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_ ); + + typedef MultTrait_< ResultType, ResultType_ > 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_ 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& + Subvector::operator/=( const DenseVector& 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_ ); + BLAZE_CONSTRAINT_MUST_NOT_REQUIRE_EVALUATION( ResultType_ ); + + typedef DivTrait_< ResultType, ResultType_ > 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_ 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_, Subvector >& + Subvector::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_, Subvector >& + Subvector::operator/=( Other rhs ) +{ + BLAZE_USER_ASSERT( rhs != Other(0), "Division by zero detected" ); + + typedef DivTrait_ DT; + typedef If_< IsNumeric
, 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
::value && IsFloatingPoint
::value ) { + const Tmp tmp( Tmp(1)/static_cast( 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::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::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::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::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::Iterator + Subvector::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::Iterator + Subvector::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::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::Iterator Subvector::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::Iterator + Subvector::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::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& Subvector::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::Iterator + Subvector::find( size_t index ) +{ + const Iterator_ 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::ConstIterator + Subvector::find( size_t index ) const +{ + const ConstIterator_ 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::Iterator + Subvector::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::ConstIterator + Subvector::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::Iterator + Subvector::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::ConstIterator + Subvector::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::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::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::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::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::assign( const DenseVector& 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 // Transpose flag +template< typename VT2 > // Type of the right-hand side sparse vector +inline void Subvector::assign( const SparseVector& 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_ 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::addAssign( const DenseVector& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::addAssign( const SparseVector& rhs ) +{ + typedef AddTrait_< ResultType, ResultType_ > 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::subAssign( const DenseVector& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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::subAssign( const SparseVector& rhs ) +{ + typedef SubTrait_< ResultType, ResultType_ > 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 + +#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 + + + + +//================================================================================================= +// +// 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 +#include +#include + + +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 +#include + + + + +//================================================================================================= +// +// CACHE SIZE +// +//================================================================================================= + +#include + + + + +//================================================================================================= +// +// 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 + + + + +//================================================================================================= +// +// 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_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 + + + + +//================================================================================================= +// +// LOGGING CONFIGURATION +// +//================================================================================================= + +#include + +#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 + +#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 + +#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 + + + + +//================================================================================================= +// +// NUMERICAL PRECISION +// +//================================================================================================= + +#include + + + + +//================================================================================================= +// +// 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 NUMBER GENERATOR CONFIGURATION +// +//================================================================================================= + +#include + +#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 + + + + +//================================================================================================= +// +// 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 + + + + +//================================================================================================= +// +// 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 + + + + +//================================================================================================= +// +// STORAGE ORDER +// +//================================================================================================= + +#include + +#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 +#include +#include + + + + +//================================================================================================= +// +// THRESHOLDS +// +//================================================================================================= + +#include + + + + +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 + + + + +//================================================================================================= +// +// TRANSPOSE FLAG +// +//================================================================================================= + +#include + +#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 +#include + + + + +//================================================================================================= +// +// 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 +#elif BLAZE_SSE4_MODE +# include +#elif BLAZE_SSSE3_MODE +# include +#elif BLAZE_SSE3_MODE +# include +#elif BLAZE_SSE2_MODE +# include +#elif BLAZE_SSE_MODE +# include +#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 +#include +#include +#include + + +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::value_type; + + if( IsNothrowMoveAssignable::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( *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( *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 +#include +#include + + +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 other; //!< Type of the other allocator. + }; + //********************************************************************************************** + + //**Constructors******************************************************************************** + /*!\name Constructors */ + //@{ + explicit inline AlignedAllocator(); + + template< typename Type2 > + inline AlignedAllocator( const AlignedAllocator& ); + //@} + //********************************************************************************************** + + //**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::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::AlignedAllocator( const AlignedAllocator& 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::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::Pointer + AlignedAllocator::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::ConstPointer + AlignedAllocator::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::Pointer + AlignedAllocator::allocate( size_t numObjects, const void* localityHint ) +{ + UNUSED_PARAMETER( localityHint ); + + const size_t alignment( AlignmentOf::value ); + + if( alignment >= 8UL ) { + return reinterpret_cast( allocate_backend( numObjects*sizeof(Type), alignment ) ); + } + else { + return static_cast( 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::deallocate( Pointer ptr, size_t numObjects ) +{ + UNUSED_PARAMETER( numObjects ); + + if( ptr == nullptr ) + return; + + const size_t alignment( AlignmentOf::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::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::destroy( Pointer ptr ) noexcept +{ + ptr->~Type(); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name AlignedAllocator operators */ +//@{ +template< typename T1, typename T2 > +inline bool operator==( const AlignedAllocator& lhs, const AlignedAllocator& rhs ) noexcept; + +template< typename T1, typename T2 > +inline bool operator!=( const AlignedAllocator& lhs, const AlignedAllocator& 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& lhs, const AlignedAllocator& 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& lhs, const AlignedAllocator& 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 +#include +#include +#include +#include + + +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 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 array2{ 1, 2, 3 }; // Directly initialized array + blaze::AlignedArray 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::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::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::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::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::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::Reference + AlignedArray::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::ConstReference + AlignedArray::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::Reference + AlignedArray::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::ConstReference + AlignedArray::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::Pointer + AlignedArray::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::ConstPointer + AlignedArray::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::Iterator + AlignedArray::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::ConstIterator + AlignedArray::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::ConstIterator + AlignedArray::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::Iterator + AlignedArray::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::ConstIterator + AlignedArray::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::ConstIterator + AlignedArray::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::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 +#include + + +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 +#include + + +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 + + +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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include + + +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 : 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::convert( From* from ) +{ + return dynamic_cast( 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 : 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::convert( From* from ) +{ + return static_cast( 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::convert( const From& from ) +{ + return static_cast( 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 : 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::convert( From* from ) +{ + return CastConverter::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 : 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::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 : 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::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. +*/ +template<> +struct Converter : 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::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( 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::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( 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( const std::string& from ) +{ + return static_cast( 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( const std::string& from ) +{ + return static_cast( 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( 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::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( 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( const char* const from ) +{ + return static_cast( 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( const char* const from ) +{ + return static_cast( 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( 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::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( 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( char* const from ) +{ + return static_cast( 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( char* const from ) +{ + return static_cast( 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( 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 +#include + + +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 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 ); +} +//************************************************************************************************* + +} // 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::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::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::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 +{}; +/*! \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::value >::Type; + using Type2 = DisableIfTrue_< IsBuiltin::value >; + \endcode +*/ +template< bool Condition // Compile time condition + , typename T=void > // The type to be instantiated +using DisableIfTrue_ = typename DisableIfTrue::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 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, 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, 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 +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\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 >::Type; + using Type2 = DisableIf_< IsBuiltin >; + \endcode +*/ +template< typename Condition // Compile time condition + , typename T=void > // The type to be instantiated +using DisableIf_ = typename DisableIf::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::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::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::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 +{}; +/*! \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::value >::Type; + using Type2 = EnableIfTrue_< IsBuiltin::value >; + \endcode +*/ +template< bool Condition // Compile time condition + , typename T=void > // The type to be instantiated +using EnableIfTrue_ = typename EnableIfTrue::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 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, 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, 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 +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\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 >::Type; + using Type2 = EnableIf_< IsBuiltin >; + \endcode +*/ +template< typename Condition // Compile time condition + , typename T=void > // The type to be instantiated +using EnableIf_ = typename EnableIf::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 + + + + +//================================================================================================= +// +// 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 + \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 + \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 + \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 + \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 + \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 + \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 + \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 + + +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; +//************************************************************************************************* + +} // 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 +#include +#include +#include +#include +#include + + +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::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 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(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(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 +#include +#include +#include + + +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 + + +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::value // Evaluates to 3 + IntegralConstant::ValueType // Results in long + \endcode +*/ +template< typename T, T N > +struct IntegralConstant : public std::integral_constant +{ + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + using ValueType = T; + using Type = IntegralConstant; + /*! \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::value // Evaluates to true + BoolConstant::ValueType // Results in bool + \endcode +*/ +template< bool B > +using BoolConstant = IntegralConstant; +//************************************************************************************************* + +} // 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 +#include + + +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: +// +//
    +//
  • Integral data types
  • +//
      +//
    • unsigned char, signed char, char, wchar_t
    • +//
    • unsigned short, short
    • +//
    • unsigned int, int
    • +//
    • unsigned long, long
    • +//
    • size_t, ptrdiff_t (for certain 64-bit compilers)
    • +//
    +//
  • Floating point data types
  • +//
      +//
    • float
    • +//
    • double
    • +//
    • long double
    • +//
    +//
+// +// 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::inf(); + + // Negative infinity value + double d = Limits::ninf(); + \endcode +*/ +template< typename Type > +struct Limits +{}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// SPECIALIZATIONS +// +//================================================================================================= + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Limits specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive unsigned char value. */ + static inline unsigned char inf() { return std::numeric_limits::max(); } +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Limits specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive char value. */ + static inline char inf () { return std::numeric_limits::max(); } + + /*!\brief Negative infinity value. + // \return The largest possible negative char value. */ + static inline char ninf() { return std::numeric_limits::min(); } +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Limits specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive signed char value. */ + static inline signed char inf () { return std::numeric_limits::max(); } + + /*!\brief Negative infinity value. + // \return The largest possible negative signed char value. */ + static inline signed char ninf() { return std::numeric_limits::min(); } +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Limits specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive wchar_t value. */ + static inline wchar_t inf () { return std::numeric_limits::max(); } + + /*!\brief Negative infinity value. + // \return The largest possible negative wchar_t value. */ + static inline wchar_t ninf() { return std::numeric_limits::min(); } +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Limits specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive unsigned short value. */ + static inline unsigned short inf() { return std::numeric_limits::max(); } +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Limits specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive short value. */ + static inline short inf () { return std::numeric_limits::max(); } + + /*!\brief Negative infinity value. + // \return The largest possible negative short value. */ + static inline short ninf() { return std::numeric_limits::min(); } +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Limits specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive unsigned int value. */ + static inline unsigned int inf() { return std::numeric_limits::max(); } +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Limits specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive int value. */ + static inline int inf () { return std::numeric_limits::max(); } + + /*!\brief Negative infinity value. + // \return The largest possible negative int value. */ + static inline int ninf() { return std::numeric_limits::min(); } +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Limits specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive unsigned long value. */ + static inline unsigned long inf() { return std::numeric_limits::max(); } +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Limits specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive long value. */ + static inline long inf () { return std::numeric_limits::max(); } + + /*!\brief Negative infinity value. + // \return The largest possible negative long value. */ + static inline long ninf() { return std::numeric_limits::min(); } +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +#if defined(_WIN64) +/*! \cond BLAZE_INTERNAL */ +/*!\brief Limits specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive size_t value. */ + static inline size_t inf() { return std::numeric_limits::max(); } +}; +/*! \endcond */ +#endif +//************************************************************************************************* + + +//************************************************************************************************* +#if defined(_WIN64) +/*! \cond BLAZE_INTERNAL */ +/*!\brief Limits specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive ptrdiff_t value. */ + static inline ptrdiff_t inf () { return std::numeric_limits::max(); } + + /*!\brief Negative infinity value. + // \return The largest possible negative ptrdiff_t value. */ + static inline ptrdiff_t ninf() { return std::numeric_limits::min(); } +}; +/*! \endcond */ +#endif +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Limits specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive float value. */ + static inline float inf () { return std::numeric_limits::max(); } + + /*!\brief Negative infinity value. + // \return The largest possible negative float value. */ + static inline float ninf() { return -std::numeric_limits::max(); } + + /*!\brief Machine epsilon. + // \return The smallest possible difference between two float values. */ + static inline float epsilon() { return std::numeric_limits::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 specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive double value. */ + static inline double inf () { return std::numeric_limits::max(); } + + /*!\brief Negative infinity value. + // \return The largest possible negative double value. */ + static inline double ninf() { return -std::numeric_limits::max(); } + + /*!\brief Machine epsilon. + // \return The smallest possible difference between two double values. */ + static inline double epsilon() { return std::numeric_limits::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 specialization. +// \ingroup util +*/ +template<> +struct Limits +{ + /*!\brief Positive infinity value. + // \return The largest possible positive long double value. */ + static inline long double inf () { return std::numeric_limits::max(); } + + /*!\brief Negative infinity value. + // \return The largest possible negative long double value. */ + static inline long double ninf() { return -std::numeric_limits::max(); } + + /*!\brief Machine epsilon. + // \return The smallest possible difference between two long double values. */ + static inline long double epsilon() { return std::numeric_limits::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 +#include +#include +#include +#include +#include +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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( 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( address ) ); +#else + free( const_cast( 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( 10UL ); + \endcode +*/ +template< typename T > +EnableIf_< IsBuiltin, T* > allocate( size_t size ) +{ + const size_t alignment( AlignmentOf::value ); + + if( alignment >= 8UL ) { + return reinterpret_cast( 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* > allocate( size_t size ) +{ + const size_t alignment ( AlignmentOf::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( raw ) = size; + + T* const address( reinterpret_cast( raw + headersize ) ); + size_t i( 0UL ); + + try { + for( ; i +EnableIf_< IsBuiltin > deallocate( T* address ) noexcept +{ + if( address == nullptr ) + return; + + const size_t alignment( AlignmentOf::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 > deallocate( T* address ) +{ + if( address == nullptr ) + return; + + const size_t alignment ( AlignmentOf::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( address ) - headersize; + + const size_t size( *reinterpret_cast( raw ) ); + for( size_t i=0UL; i +#include +#include +#include + + +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 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::Block::init() +{ + rawMemory_ = new FreeObject[ Blocksize ]; + for( size_t i=0; i +inline void MemoryPool::Block::free() +{ + delete [] rawMemory_; +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// CLASS MEMORYPOOL +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Constructor of the memory pool. +*/ +template< typename Type, size_t Blocksize > +inline MemoryPool::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::~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::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::free( void* rawMemory ) +{ + FreeObject* ptr = reinterpret_cast( 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::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(toRelease) ); + const byte_t* const ptr2( reinterpret_cast(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 +#include +#include + + +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( address ) % AlignmentOf::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( b ); // Static down-cast + \endcode +*/ +template< typename To, typename From > +inline To* static_pointer_cast( From* ptr ) +{ + return static_cast( 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( b ); // Dynamic down-cast + \endcode +*/ +template< typename To, typename From > +inline To* dynamic_pointer_cast( From* ptr ) +{ + return dynamic_cast( 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
( 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( 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( raw ); // Reinterpretation cast + \endcode +*/ +template< typename To, typename From > +inline To* reinterpret_pointer_cast( From* ptr ) +{ + return reinterpret_cast( ptr ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// SMART POINTER CAST OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name Smart pointer cast operators */ +//@{ +template< typename To, template class S, typename From > inline S static_pointer_cast( S ptr ); +template< typename To, template class S, typename From > inline S dynamic_pointer_cast( S ptr ); +template< typename To, template class S, typename From > inline S const_pointer_cast( S ptr); +template< typename To, template class S, typename From > inline S reinterpret_pointer_cast( S 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 BPtr; + typedef SharedPtr DPtr; + + BPtr b = BPtr( new D() ); // Base smart pointer to a derived class object + DPtr d = static_pointer_cast( b ); // Static down-cast + \endcode +*/ +template< typename To, template class S, typename From > +inline S static_pointer_cast( S ptr ) +{ + return S( static_cast( 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 BPtr; + typedef SharedPtr DPtr; + + BPtr b = ...; // Base smart pointer + DPtr d = dynamic_pointer_cast( b ); // Dynamic down-cast + \endcode +*/ +template< typename To, template class S, typename From > +inline S dynamic_pointer_cast( S ptr ) +{ + return S( dynamic_cast( 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 APtr; + typedef SharedPtr ConstAPtr; + + ConstAPtr a1; // Smart pointer to a constant A object + APtr a2 = const_pointer_cast( a1 ); // Const cast to a smart pointer to a non-constant A object + \endcode +*/ +template< typename To, template class S, typename From > +inline S const_pointer_cast( S ptr ) +{ + return S( const_cast( 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 class S, typename From > +inline S reinterpret_pointer_cast( S ptr ) +{ + return S( reinterpret_cast( 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 +#include +#include +#include +#include +#include +#include +#include + +#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 + + +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 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& 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::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::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::PtrIterator( const PtrIterator& 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& PtrIterator::operator++() +{ + ++it_; + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Post-increment operator. +// +// \return The incremented pointer iterator. +*/ +template< typename Type > +inline PtrIterator PtrIterator::operator++( int ) +{ + PtrIterator tmp( *this ); + ++it_; + return tmp; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Pre-decrement operator. +// +// \return Reference to the decremented pointer iterator. +*/ +template< typename Type > +inline PtrIterator& PtrIterator::operator--() +{ + --it_; + return *this; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Post-decrement operator. +// +// \return The decremented pointer iterator. +*/ +template< typename Type > +inline PtrIterator PtrIterator::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& PtrIterator::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 PtrIterator::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& PtrIterator::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 PtrIterator::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::DifferenceType PtrIterator::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::PointerType PtrIterator::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::PointerType PtrIterator::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::PointerType PtrIterator::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::IteratorType& PtrIterator::base() const +{ + return it_; +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name PtrIterator operators */ +//@{ +template< typename TypeL, typename TypeR > +inline bool operator==( const PtrIterator& lhs, const PtrIterator& rhs ); + +template< typename TypeL, typename TypeR > +inline bool operator!=( const PtrIterator& lhs, const PtrIterator& rhs ); + +template< typename TypeL, typename TypeR > +inline bool operator<( const PtrIterator& lhs, const PtrIterator& rhs ); + +template< typename TypeL, typename TypeR > +inline bool operator>( const PtrIterator& lhs, const PtrIterator& rhs ); + +template< typename TypeL, typename TypeR > +inline bool operator<=( const PtrIterator& lhs, const PtrIterator& rhs ); + +template< typename TypeL, typename TypeR > +inline bool operator>=( const PtrIterator& lhs, const PtrIterator& 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& lhs, const PtrIterator& 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& lhs, const PtrIterator& 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& lhs, const PtrIterator& 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& lhs, const PtrIterator& 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& lhs, const PtrIterator& 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& lhs, const PtrIterator& 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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 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 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 vector; + + // pe style: + blaze::PtrVector 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& vector ) + { + blaze::PtrVector::CastIterator begin = vector.begin(); + blaze::PtrVector::CastIterator end = vector.end(); + + // 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& vector ) + { + blaze::PtrVector::ConstCastIterator begin = vector.begin(); + blaze::PtrVector::ConstCastIterator end = vector.end(); + + // 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::CastIterator + { + CastIterator( const blaze::PtrVector::CastIterator& it ) + : blaze::PtrVector::CastIterator( it ) // Initializing the base class + {} + }; + + template< typename C > + CastIterator begin(); + + template< typename C > + CastIterator end(); + + private: + blaze::PtrVector 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::CastIterator 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 Iterator; //!< Iterator over non-const objects. + typedef PtrIterator 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& 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& 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 begin(); + template< typename C > inline ConstCastIterator begin() const; + + inline Iterator end(); + inline ConstIterator end() const; + template< typename C > inline CastIterator end(); + template< typename C > inline ConstCastIterator 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 erase ( CastIterator pos ); + inline Iterator release( Iterator pos ); + template< typename C > inline CastIterator release( CastIterator 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& lhs, const CastIterator& 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& lhs, const ConstCastIterator& 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& lhs, const CastIterator& 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& lhs, const ConstCastIterator& 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& lhs, const CastIterator& 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& lhs, const ConstCastIterator& 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& lhs, const CastIterator& 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& lhs, const ConstCastIterator& 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::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::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 // 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::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 // Growth policy +inline PtrVector::~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& PtrVector::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& PtrVector::operator=( const PtrVector& 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::SizeType PtrVector::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::SizeType PtrVector::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 AVector; + AVector vector; + + AVector::SizeType total = vector.size(); // Calculating the total number of pointers + AVector::SizeType numB = vector.size(); // 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::SizeType PtrVector::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( *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( 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::SizeType PtrVector::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::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::ReferenceType PtrVector::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::ConstReferenceType PtrVector::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::ReferenceType PtrVector::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::ConstReferenceType PtrVector::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::ReferenceType PtrVector::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::ConstReferenceType PtrVector::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::Iterator PtrVector::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::ConstIterator PtrVector::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& vector ) + { + blaze::PtrVector::CastIterator begin = vector.begin(); + blaze::PtrVector::CastIterator end = vector.end(); + + // 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& vector ) + { + blaze::PtrVector::ConstCastIterator begin = vector.begin(); + blaze::PtrVector::ConstCastIterator end = vector.end(); + + // 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::BLAZE_TEMPLATE CastIterator PtrVector::begin() +{ + return CastIterator( 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& vector ) + { + blaze::PtrVector::CastIterator begin = vector.begin(); + blaze::PtrVector::CastIterator end = vector.end(); + + // 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& vector ) + { + blaze::PtrVector::ConstCastIterator begin = vector.begin(); + blaze::PtrVector::ConstCastIterator end = vector.end(); + + // 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::BLAZE_TEMPLATE ConstCastIterator PtrVector::begin() const +{ + return ConstCastIterator( 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::Iterator PtrVector::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::ConstIterator PtrVector::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& vector ) + { + blaze::PtrVector::CastIterator begin = vector.begin(); + blaze::PtrVector::CastIterator end = vector.end(); + + // 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& vector ) + { + blaze::PtrVector::ConstCastIterator begin = vector.begin(); + blaze::PtrVector::ConstCastIterator end = vector.end(); + + // 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::BLAZE_TEMPLATE CastIterator PtrVector::end() +{ + return CastIterator( 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& vector ) + { + blaze::PtrVector::CastIterator begin = vector.begin(); + blaze::PtrVector::CastIterator end = vector.end(); + + // 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& vector ) + { + blaze::PtrVector::ConstCastIterator begin = vector.begin(); + blaze::PtrVector::ConstCastIterator end = vector.end(); + + // 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::BLAZE_TEMPLATE ConstCastIterator PtrVector::end() const +{ + return ConstCastIterator( 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::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::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::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::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::Iterator PtrVector::insert( Iterator pos, PointerType p ) +{ + T** const base = const_cast( 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::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::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::Iterator PtrVector::erase( Iterator pos ) +{ + T** const base = const_cast( 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::BLAZE_TEMPLATE CastIterator + PtrVector::erase( CastIterator pos ) +{ + T** const base = const_cast( pos.base() ); + deleteElement( *base ); + std::copy( base+1, end_, base ); + + --size_; + --end_; + + return CastIterator( 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::Iterator PtrVector::release( Iterator pos ) +{ + T** const base = const_cast( 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::BLAZE_TEMPLATE CastIterator + PtrVector::release( CastIterator pos ) +{ + T** const base = const_cast( pos.base() ); + std::copy( base+1, end_, base ); + + --size_; + --end_; + + return CastIterator( 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::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::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::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::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::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::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::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::insert( Iterator pos, IteratorType first, IteratorType last, + std::random_access_iterator_tag ) +{ + T** const base = const_cast( 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::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& lhs, const PtrVector& rhs ); + +template< typename T, typename D, typename G > +inline bool operator!=( const PtrVector& lhs, const PtrVector& rhs ); + +template< typename T, typename D, typename G > +inline void swap( PtrVector& a, PtrVector& 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& lhs, const PtrVector& 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& lhs, const PtrVector& 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& a, PtrVector& 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::CastIterator begin; + blaze::PtrVector::CastIterator 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::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& 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::CastIterator::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::CastIterator::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( *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( 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::CastIterator::CastIterator( const CastIterator& 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::BLAZE_TEMPLATE CastIterator& + PtrVector::CastIterator::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( *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( ++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::BLAZE_TEMPLATE CastIterator + PtrVector::CastIterator::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( *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( ++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::BLAZE_TEMPLATE CastIterator::PointerType + PtrVector::CastIterator::operator*() const +{ + return static_cast( *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::BLAZE_TEMPLATE CastIterator::PointerType + PtrVector::CastIterator::operator->() const +{ + return static_cast( *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::BLAZE_TEMPLATE CastIterator::IteratorType& + PtrVector::CastIterator::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::BLAZE_TEMPLATE CastIterator::IteratorType& + PtrVector::CastIterator::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::ConstCastIterator begin; + blaze::PtrVector::ConstCastIterator 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::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& it ); + + template< typename Other > + inline ConstCastIterator( const typename PtrVector::BLAZE_TEMPLATE CastIterator& 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::ConstCastIterator::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::ConstCastIterator::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( *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( 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::ConstCastIterator::ConstCastIterator( const ConstCastIterator& 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::ConstCastIterator::ConstCastIterator( const typename PtrVector::BLAZE_TEMPLATE CastIterator& 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::BLAZE_TEMPLATE ConstCastIterator& + PtrVector::ConstCastIterator::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( *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( ++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::BLAZE_TEMPLATE ConstCastIterator + PtrVector::ConstCastIterator::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( *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( ++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::BLAZE_TEMPLATE ConstCastIterator::PointerType + PtrVector::ConstCastIterator::operator*() const +{ + return static_cast( *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::BLAZE_TEMPLATE ConstCastIterator::PointerType + PtrVector::ConstCastIterator::operator->() const +{ + return static_cast( *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::BLAZE_TEMPLATE ConstCastIterator::IteratorType& + PtrVector::ConstCastIterator::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::BLAZE_TEMPLATE ConstCastIterator::IteratorType& + PtrVector::ConstCastIterator::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 +#include +#include +#include +#include +#include +#include +#include + + +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(); +// - 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(); + double d = rand( 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 c1 = rand< complex >(); + complex c2 = rand< complex >( 1.0F, 4.0F ); + complex c3 = rand< complex >( 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::seed_( defaultSeed() ); +template< typename Type > Type Random::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::generate() const +{ + std::uniform_int_distribution dist( 0, std::numeric_limits::max() ); + return dist( Random::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::generate( T min, T max ) const +{ + BLAZE_INTERNAL_ASSERT( min <= max, "Invalid min/max value pair" ); + std::uniform_int_distribution dist( min, max ); + return dist( Random::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::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::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 +{ + 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::generate() const +{ + std::uniform_real_distribution dist( 0.0, 1.0 ); + return dist( Random::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::generate( float min, float max ) const +{ + BLAZE_INTERNAL_ASSERT( min <= max, "Invalid min/max values" ); + std::uniform_real_distribution dist( min, max ); + return dist( Random::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::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::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 +{ + 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::generate() const +{ + std::uniform_real_distribution dist( 0.0, 1.0 ); + return dist( Random::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::generate( double min, double max ) const +{ + BLAZE_INTERNAL_ASSERT( min <= max, "Invalid min/max values" ); + std::uniform_real_distribution dist( min, max ); + return dist( Random::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::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::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 +{ + 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::generate() const +{ + std::uniform_real_distribution dist( 0.0, 1.0 ); + return dist( Random::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::generate( long double min, long double max ) const +{ + BLAZE_INTERNAL_ASSERT( min <= max, "Invalid min/max values" ); + std::uniform_real_distribution dist( min, max ); + return dist( Random::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::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::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 > +{ + public: + //**Generate functions************************************************************************** + /*!\name Generate functions */ + //@{ + inline const complex generate() const; + inline const complex generate( const T& min, const T& max ) const; + inline const complex generate( const T& realmin, const T& realmax, + const T& imagmin, const T& imagmax ) const; + //@} + //********************************************************************************************** + + //**Randomize functions************************************************************************* + /*!\name Randomize functions */ + //@{ + inline void randomize( complex& value ) const; + inline void randomize( complex& value, const T& min, const T& max ) const; + inline void randomize( complex& 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 Rand< complex >::generate() const +{ + Rand tmp; + return complex( 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 Rand< complex >::generate( const T& min, const T& max ) const +{ + Rand tmp; + return complex( 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 Rand< complex >::generate( const T& realmin, const T& realmax, + const T& imagmin, const T& imagmax ) const +{ + Rand tmp; + return complex( 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 >::randomize( complex& 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 >::randomize( complex& 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 >::randomize( complex& 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 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 tmp; + return tmp.generate( std::forward( 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 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 tmp; + tmp.randomize( value, std::forward( 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( 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::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::seed_ = seed; + Random::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 + +#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 +#include + +#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 + + +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 + #include + + template< typename T > + class RotationMatrix { + ... + BLAZE_STATIC_ASSERT( IsFloatingPoint::value ); + // ... or ... + BLAZE_STATIC_ASSERT_MSG( IsFloatingPoint::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::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::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 +#include +#include + + +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 +{ + 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 + + +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 SystemClockID; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Handle for the system clock of the Blaze library. +// \ingroup util +*/ +typedef std::shared_ptr 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; + }; + ... + }; + + typedef Alloc AI; + typedef AI::template rebind::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::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 +#include +#include +#include + + +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::condition_variable > BoostThread; + + typedef blaze::Thread< std::thread + , std::mutex + , std::unique_lock + , 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 + #include + + // 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 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 ThreadPoolType; //!< Type of the managing thread pool. + typedef std::unique_ptr 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; + /*! \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::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::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 )... ) ); +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// 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::~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::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::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::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::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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +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::condition_variable > BoostThreadPool; + + typedef blaze::ThreadPool< std::thread + , std::mutex + , std::unique_lock + , 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 + #include + + // 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 ManagedThread; //!< Type of the managed threads. + typedef PtrVector 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; + /*! \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::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::~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::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::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::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::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::schedule( Callable func, Args&&... args ) +{ + Lock lock( mutex_ ); + taskqueue_.push( std::bind( func, std::forward( 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::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_; ihasTerminated() ) { + 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::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::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::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::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 +# include +# include +# include +#else +# include +# include +# include +#endif +#include +#include + + +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( timeptr.time ) + static_cast( timeptr.millitm )/1E3 ); +#else + struct timeval tp; + gettimeofday( &tp, nullptr ); + return ( static_cast( tp.tv_sec ) + static_cast( 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( SysTime.wSecond ) + static_cast( SysTime.wMilliseconds )/1E3 ); + } +#else + struct rusage ruse; + getrusage( RUSAGE_SELF, &ruse ); + return ( static_cast( ruse.ru_utime.tv_sec ) + static_cast( 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 +#include +#include +#include +#include + +#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 + + +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; +//************************************************************************************************* + +} // 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 +#include + + +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::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::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::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::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::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::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::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::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::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::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 > +{ + //**Member enumeration************************************************************************** + enum { value = 1 + Length::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, 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, 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 > +{ + //**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, Type > +{ + //**Member enumeration************************************************************************** + enum { value = Contains::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, 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::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 > +{ + //**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, Type > +{ + private: + //**Member enumeration************************************************************************** + enum { tmp = IndexOf::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::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 > +{ + //**Type definitions**************************************************************************** + typedef TypeList 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, Type > +{ + //**Type definitions**************************************************************************** + typedef TypeList< Head, typename Append::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::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 > +{ + //**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, Type > +{ + //**Type definitions**************************************************************************** + typedef TypeList::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::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 > +{ + //**Type definitions**************************************************************************** + typedef typename EraseAll::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, Type > +{ + //**Type definitions**************************************************************************** + typedef TypeList::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::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 > +{ + private: + //**Type definitions**************************************************************************** + typedef typename Unique::Result TL1; + typedef typename Erase::Result TL2; + //********************************************************************************************** + + public: + //**Type definitions**************************************************************************** + typedef TypeList 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 +#include + + +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 +#include +#include + + +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::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& UnsignedValue::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::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::get() const +{ + return value_; +} +//************************************************************************************************* + + + + +//================================================================================================= +// +// GLOBAL OPERATORS +// +//================================================================================================= + +//************************************************************************************************* +/*!\name UnsignedValue operators */ +//@{ +template< typename T1, typename T2 > +inline bool operator==( const UnsignedValue& lhs, const UnsignedValue& rhs ); + +template< typename T1, typename T2 > +inline bool operator!=( const UnsignedValue& lhs, const UnsignedValue& rhs ); + +template< typename T1, typename T2 > +inline bool operator< ( const UnsignedValue& lhs, const UnsignedValue& rhs ); + +template< typename T1, typename T2 > +inline bool operator> ( const UnsignedValue& lhs, const UnsignedValue& rhs ); + +template< typename T1, typename T2 > +inline bool operator<=( const UnsignedValue& lhs, const UnsignedValue& rhs ); + +template< typename T1, typename T2 > +inline bool operator>=( const UnsignedValue& lhs, const UnsignedValue& rhs ); + +template< typename T > +inline std::ostream& operator<<( std::ostream& os, const UnsignedValue& uv ); + +template< typename T > +std::istream& operator>>( std::istream& is, UnsignedValue& 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& lhs, const UnsignedValue& 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& lhs, const UnsignedValue& 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& lhs, const UnsignedValue& 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& lhs, const UnsignedValue& 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& lhs, const UnsignedValue& 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& lhs, const UnsignedValue& 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& 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& 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 +#include +#include +#include + +#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 + + +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::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::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 + + +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::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::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 + + +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::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::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::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::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::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::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::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::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 + + +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::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::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::value && !::blaze::IsBaseOf::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::value || ::blaze::IsBaseOf::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::value || ::blaze::IsConvertible::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 + + +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::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::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 + + +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, ignoring the cv-qualifiers). In case \a T is +// not of type \a complex a compilation error is created. +*/ +#define BLAZE_CONSTRAINT_MUST_BE_COMPLEX_DOUBLE_TYPE(T) \ + static_assert( ::blaze::IsComplexDouble::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, ignoring the cv-qualifiers). In case \a T is of +// type \a complex a compilation error is created. +*/ +#define BLAZE_CONSTRAINT_MUST_NOT_BE_COMPLEX_DOUBLE_TYPE(T) \ + static_assert( !::blaze::IsComplexDouble::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 + + +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, ignoring the cv-qualifiers). In case \a T is +// not of type \a complex a compilation error is created. +*/ +#define BLAZE_CONSTRAINT_MUST_BE_COMPLEX_FLOAT_TYPE(T) \ + static_assert( ::blaze::IsComplexFloat::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, ignoring the cv-qualifiers). In case \a T is of +// type \a complex a compilation error is created. +*/ +#define BLAZE_CONSTRAINT_MUST_NOT_BE_COMPLEX_FLOAT_TYPE(T) \ + static_assert( !::blaze::IsComplexFloat::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 + + +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::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::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 RotationMatrix + { + // ... + static_assert( std::is_floating_point::value, "Non-floating point type detected" ); + // ... + }; + \endcode + +// The Blaze library extends this functionality in the form of compile time constraint macros: + + \code + template + 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 + + 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::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 + + +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::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::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::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::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::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::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::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::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::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::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::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::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 + + +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::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::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 + + +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::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::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::value && !::blaze::IsBaseOf::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::value || ::blaze::IsBaseOf::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 + + +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::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::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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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::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::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 + + +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::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::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 + + +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::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::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::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::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::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::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::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::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::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::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 + + +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()[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()] ) > 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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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::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::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 + + +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 + + +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 + + +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 +#include +#include +#include +#include + + +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 + + +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 +#include +#include +#include + + +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 +#include +#include +#include + + +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 +{ + 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 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 + + +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 + + +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 + + +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::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 + : 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, IsSigned >::value // Evaluates to 1 + And< IsIntegral, IsFloatingPoint >::value // Evaluates to 0 + And< IsFloat , IsDouble >::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::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 + + +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::value // Evaluates to true + Bool::ValueType // Results in bool + \endcode +*/ +template< bool C > +struct Bool : public IntegralConstant +{}; +//************************************************************************************************* + +} // 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 + + +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 +{}; +//************************************************************************************************* + +} // 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 + + +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 + + +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 +{ + 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::value, T1, T2 >::Type; + using Type2 = IfTrue_< IsBuiltin::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::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, T2, T3 >::Type; + using Type2 = If_< IsBuiltin, 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::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 + + +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 +{}; +//************************************************************************************************* + +} // 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 + + +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 + + +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 +{}; +//************************************************************************************************* + +} // 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 +#include + + +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, 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 +#include + + +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 > +{}; +//************************************************************************************************* + +} // 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 +#include + + +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 +#include + + +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 +#include +#include +#include +#include + + +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 + + +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 >::value // Evaluates to false + Not< IsDouble >::value // Evaluates to true + Not< IsSigned >::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 + + +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::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 + : 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, IsSigned >::value // Evaluates to 1 + Or< IsIntegral, IsFloatingPoint >::value // Evaluates to 1 + Or< IsFloat , IsDouble >::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::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 +#include + + +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 +#include + + +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 +{}; +//************************************************************************************************* + +} // 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 +#include + + +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 + + +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 , IsUnsigned >::value // Evaluates to 1 + Xor< IsIntegral, IsFloatingPoint >::value // Evaluates to 1 + Xor< IsSigned , IsIntegral >::value // Evaluates to 0 + Xor< IsUnsigned, IsFloatingPoint >::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 + + +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 +#include + + +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::operator()( size_t old, size_t minimum ) const +{ + const size_t needed( max( 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 + + +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 + + +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 ptrDelete // Uses delete to free resources + DefaultDelete 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::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 +{ + //**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::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 +#include + + +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::operator()( size_t old, size_t minimum ) const +{ + const size_t needed( max( 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 +#include + + +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( 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 + + +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 +#include +#include +#include +#include +#include + + +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 archive( "filename", std::ofstream::trunc ); + archive << pod; + } + + // Reconstituting the POD from the binary representation + { + POD pod; + Archive 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, Archive& > operator<<( const T& value ); + + template< typename T > + DisableIf_< IsNumeric, Archive& > operator<<( const T& value ); + + template< typename T > + EnableIf_< IsNumeric, Archive& > operator>>( T& value ); + + template< typename T > + DisableIf_< IsNumeric, Archive& > operator>>( T& value ); + + template< typename Type > + inline EnableIf_< IsNumeric, Archive& > write( const Type* array, size_t count ); + + template< typename Type > + inline EnableIf_< IsNumeric, 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 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::Archive( Args&&... args ) + : ptr_ ( new Stream( std::forward( 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::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::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::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, Archive& > Archive::operator<<( const T& value ) +{ + typedef typename Stream::char_type CharType; + stream_.write( reinterpret_cast( &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, Archive& > Archive::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, Archive& > Archive::operator>>( T& value ) +{ + typedef typename Stream::char_type CharType; + stream_.read( reinterpret_cast( &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, Archive& > Archive::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, Archive& > + Archive::write( const Type* array, size_t count ) +{ + typedef typename Stream::char_type CharType; + stream_.write( reinterpret_cast( 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, Archive& > + Archive::read( Type* array, size_t count ) +{ + typedef typename Stream::char_type CharType; + stream_.read( reinterpret_cast( 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::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::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::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::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::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::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::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::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 +#include + + +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 + { + ... + }; + + // #2: Approach by composition + class Viewer + { + private: + Dependency 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 dependency_; //!< Handle to the lifetime dependency. + //@} + //********************************************************************************************** +}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// CONSTRUCTOR +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Default constructor for Dependency. +*/ +template< typename T > // Type of the lifetime dependency +inline Dependency::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 +#include +#include +#include +#include +#include +#include + + +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::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 +{ + 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 +{ + typedef typename TypeAt::Result D1; + + enum : bool { value = HasCyclicDependency::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 +{ + typedef typename TypeAt::Result D1; + typedef typename TypeAt::Result D2; + + enum : bool { value = HasCyclicDependency::value>::value || + HasCyclicDependency::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 +{ + typedef typename TypeAt::Result D1; + typedef typename TypeAt::Result D2; + typedef typename TypeAt::Result D3; + + enum : bool { value = HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::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 +{ + typedef typename TypeAt::Result D1; + typedef typename TypeAt::Result D2; + typedef typename TypeAt::Result D3; + typedef typename TypeAt::Result D4; + + enum : bool { value = HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::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 +{ + typedef typename TypeAt::Result D1; + typedef typename TypeAt::Result D2; + typedef typename TypeAt::Result D3; + typedef typename TypeAt::Result D4; + typedef typename TypeAt::Result D5; + + enum : bool { value = HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::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 +{ + typedef typename TypeAt::Result D1; + typedef typename TypeAt::Result D2; + typedef typename TypeAt::Result D3; + typedef typename TypeAt::Result D4; + typedef typename TypeAt::Result D5; + typedef typename TypeAt::Result D6; + + enum : bool { value = HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::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 +{ + typedef typename TypeAt::Result D1; + typedef typename TypeAt::Result D2; + typedef typename TypeAt::Result D3; + typedef typename TypeAt::Result D4; + typedef typename TypeAt::Result D5; + typedef typename TypeAt::Result D6; + typedef typename TypeAt::Result D7; + + enum : bool { value = HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::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 +{ + typedef typename TypeAt::Result D1; + typedef typename TypeAt::Result D2; + typedef typename TypeAt::Result D3; + typedef typename TypeAt::Result D4; + typedef typename TypeAt::Result D5; + typedef typename TypeAt::Result D6; + typedef typename TypeAt::Result D7; + typedef typename TypeAt::Result D8; + + enum : bool { value = HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::value>::value || + HasCyclicDependency::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::value > // Flag to indicate whether T is contained in TL +struct HasCyclicDependency +{ + typedef typename Append::Result ETL; + enum : bool { value = HasCyclicDependencyHelper::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 +{ + 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::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 + { + 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 + { + 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 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 instance() + { + static std::shared_ptr object( new T() ); + return object; + } + //@} + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + std::shared_ptr dependency1_; //!< Handle to the first lifetime dependency. + std::shared_ptr dependency2_; //!< Handle to the second lifetime dependency. + std::shared_ptr dependency3_; //!< Handle to the third lifetime dependency. + std::shared_ptr dependency4_; //!< Handle to the fourth lifetime dependency. + std::shared_ptr dependency5_; //!< Handle to the fifth lifetime dependency. + std::shared_ptr dependency6_; //!< Handle to the sixth lifetime dependency. + std::shared_ptr dependency7_; //!< Handle to the seventh lifetime dependency. + std::shared_ptr 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 : private NonCopyable +{ + public: + //**Type definitions**************************************************************************** + //! Type of this Singleton instance. + typedef Singleton 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 instance() + { + static std::shared_ptr object( new T() ); + return object; + } + //@} + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + std::shared_ptr dependency1_; //!< Handle to the first lifetime dependency. + std::shared_ptr dependency2_; //!< Handle to the second lifetime dependency. + std::shared_ptr dependency3_; //!< Handle to the third lifetime dependency. + std::shared_ptr dependency4_; //!< Handle to the fourth lifetime dependency. + std::shared_ptr dependency5_; //!< Handle to the fifth lifetime dependency. + std::shared_ptr dependency6_; //!< Handle to the sixth lifetime dependency. + std::shared_ptr 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 : private NonCopyable +{ + public: + //**Type definitions**************************************************************************** + //! Type of this Singleton instance. + typedef Singleton 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 instance() + { + static std::shared_ptr object( new T() ); + return object; + } + //@} + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + std::shared_ptr dependency1_; //!< Handle to the first lifetime dependency. + std::shared_ptr dependency2_; //!< Handle to the second lifetime dependency. + std::shared_ptr dependency3_; //!< Handle to the third lifetime dependency. + std::shared_ptr dependency4_; //!< Handle to the fourth lifetime dependency. + std::shared_ptr dependency5_; //!< Handle to the fifth lifetime dependency. + std::shared_ptr 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 : private NonCopyable +{ + public: + //**Type definitions**************************************************************************** + //! Type of this Singleton instance. + typedef Singleton 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 instance() + { + static std::shared_ptr object( new T() ); + return object; + } + //@} + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + std::shared_ptr dependency1_; //!< Handle to the first lifetime dependency. + std::shared_ptr dependency2_; //!< Handle to the second lifetime dependency. + std::shared_ptr dependency3_; //!< Handle to the third lifetime dependency. + std::shared_ptr dependency4_; //!< Handle to the fourth lifetime dependency. + std::shared_ptr 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 : private NonCopyable +{ + public: + //**Type definitions**************************************************************************** + //! Type of this Singleton instance. + typedef Singleton 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 instance() + { + static std::shared_ptr object( new T() ); + return object; + } + //@} + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + std::shared_ptr dependency1_; //!< Handle to the first lifetime dependency. + std::shared_ptr dependency2_; //!< Handle to the second lifetime dependency. + std::shared_ptr dependency3_; //!< Handle to the third lifetime dependency. + std::shared_ptr 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 : private NonCopyable +{ + public: + //**Type definitions**************************************************************************** + //! Type of this Singleton instance. + typedef Singleton 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 instance() + { + static std::shared_ptr object( new T() ); + return object; + } + //@} + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + std::shared_ptr dependency1_; //!< Handle to the first lifetime dependency. + std::shared_ptr dependency2_; //!< Handle to the second lifetime dependency. + std::shared_ptr 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 : private NonCopyable +{ + public: + //**Type definitions**************************************************************************** + //! Type of this Singleton instance. + typedef Singleton 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 instance() + { + static std::shared_ptr object( new T() ); + return object; + } + //@} + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + std::shared_ptr dependency1_; //!< Handle to the first lifetime dependency. + std::shared_ptr 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 : private NonCopyable +{ + public: + //**Type definitions**************************************************************************** + //! Type of this Singleton instance. + typedef Singleton 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 instance() + { + static std::shared_ptr object( new T() ); + return object; + } + //@} + //********************************************************************************************** + + private: + //**Member variables**************************************************************************** + /*!\name Member variables */ + //@{ + std::shared_ptr 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 : private NonCopyable +{ + public: + //**Type definitions**************************************************************************** + //! Type of this Singleton instance. + typedef Singleton 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 instance() + { + static std::shared_ptr 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 + + +namespace blaze { + +namespace threadpool { + +//================================================================================================= +// +// TYPE DEFINITIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Handle for a single, executable task. +// \ingroup threads +*/ +typedef std::function 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 +#include + + +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 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 + + +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 +#include + + +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 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 +#include +#include + + +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::Timer() + : counter_( 0 ) + , start_ ( 0.0 ) + , end_ ( 0.0 ) + , time_ ( 0.0 ) + , min_ ( std::numeric_limits::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::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::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::reset() +{ + counter_ = 0; + start_ = 0.0; + end_ = 0.0; + time_ = 0.0; + min_ = std::numeric_limits::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::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::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::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::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::max() const +{ + return max_; +} +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Returns the last measured time. +// +// \return The last measured time. +*/ +template< typename TP > // Timing policy +inline double Timer::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 + + +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 +#include + + +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 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 + + +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::Type // Results in 'int const volatile' + blaze::AddCV::Type // Results in 'int* const volatile' + blaze::AddCV::Type // Results in 'int&' + blaze::AddCV::Type // Results in 'int const volatile' + blaze::AddCV::Type // Results in 'int const volatile' + \endcode +*/ +template< typename T > +struct AddCV +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename std::add_cv::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::Type; + using Type2 = AddCV_; + \endcode +*/ +template< typename T > +using AddCV_ = typename AddCV::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 + + +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::Type // Results in 'int const' + blaze::AddConst::Type // Results in 'int* const' + blaze::AddConst::Type // Results in 'int&' + blaze::AddConst::Type // Results in 'int const' + blaze::AddConst::Type // Results in 'int volatile const' + \endcode +*/ +template< typename T > +struct AddConst +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename std::add_const::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::Type; + using Type2 = AddConst_; + \endcode +*/ +template< typename T > +using AddConst_ = typename AddConst::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 + + +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::Type*. + + \code + blaze::AddPointer::Type // Results in 'int*' + blaze::AddPointer::Type // Results in 'int const*' + blaze::AddPointer::Type // Results in 'int**' + blaze::AddPointer::Type // Results in 'int**' + \endcode +*/ +template< typename T > +struct AddPointer +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename std::add_pointer::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::Type; + using Type2 = AddPointer_; + \endcode +*/ +template< typename T > +using AddPointer_ = typename AddPointer::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 + + +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::Type // Results in 'int&' + blaze::AddReference::Type // Results in 'int const&' + blaze::AddReference::Type // Results in 'int*&' + blaze::AddReference::Type // Results in 'int*&' + \endcode +*/ +template< typename T > +struct AddReference +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename std::add_lvalue_reference::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::Type; + using Type2 = AddReference_; + \endcode +*/ +template< typename T > +using AddReference_ = typename AddReference::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 + + +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::Type // Results in 'int volatile' + blaze::AddVolatile::Type // Results in 'int* volatile' + blaze::AddVolatile::Type // Results in 'int&' + blaze::AddVolatile::Type // Results in 'int volatile' + blaze::AddVolatile::Type // Results in 'int const volatile' + \endcode +*/ +template< typename T > +struct AddVolatile +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename std::add_volatile::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::Type; + using Type2 = AddVolatile_; + \endcode +*/ +template< typename T > +using AddVolatile_ = typename AddVolatile::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 +#include +#include +#include + + +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::value; + //********************************************************************************************** + + public: + //********************************************************************************************** +#if BLAZE_MIC_MODE + static constexpr size_t value = ( IsVectorizable::value )?( 64UL ):( defaultAlignment ); +#elif BLAZE_AVX2_MODE + static constexpr size_t value = ( IsVectorizable::value )?( 32UL ):( defaultAlignment ); +#elif BLAZE_SSE2_MODE + static constexpr size_t value = ( IsVectorizable::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 +{ + 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::value; +#endif + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of \c AlignmentOfHelper for 'double'. +// \ingroup type_traits +*/ +template<> +struct AlignmentOfHelper +{ + 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::value; +#endif + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of \c AlignmentOfHelper for 'complex'. +// \ingroup type_traits +*/ +template<> +struct AlignmentOfHelper< complex > +{ + 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 >::value; +#endif + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of \c AlignmentOfHelper for 'complex'. +// \ingroup type_traits +*/ +template<> +struct AlignmentOfHelper< complex > +{ + 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 >::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::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::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::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::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::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::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 +#include + + +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... >::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... >::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 +#include + + +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... >::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... >::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 + + +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::Type // Results in 'int' + blaze::CommonType::Type // Results in 'double' + blaze::CommonType::Type // Results in 'float' + \endcode +*/ +template< typename... T > +struct CommonType +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename std::common_type::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::Type; + using Type2 = CommonType_; + \endcode +*/ +template< typename... T > +using CommonType_ = typename CommonType::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 + + +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::Type // Results in 'int' + blaze::Decay::Type // Results in 'int' + blaze::Decay::Type // Results in 'int' + blaze::Decay::Type // Results in 'int' + blaze::Decay::Type // Results in 'int*' + blaze::Decay::Type // Results in 'int(*)(int)' + \endcode +*/ +template< typename T > +struct Decay +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename std::decay::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::Type; + using Type2 = Decay_; + \endcode +*/ +template< typename T > +using Decay_ = typename Decay::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 + + +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, 0 >::value // Evaluates to 0 (std::vector is NOT an array type) + \endcode +*/ +template< typename T, unsigned int N > +struct Extent + : public IntegralConstant +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Partial specialization of the Extent type trait for empty array extents. +template< typename T, unsigned int N > +struct Extent + : public IntegralConstant::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 + : public IntegralConstant::value> +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Terminating partial specialization of the Extent type trait for empty array extents. +template< typename T > +struct Extent + : public IntegralConstant +{}; +/*! \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 + : public IntegralConstant +{}; +/*! \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 +#include + + +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::Type // Results in 'float' + GetElementType::Type // Results in 'double' + GetElementType::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 \ + , 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 +#include +#include + + + + +//================================================================================================= +// +// 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::value // Evaluates to 'true' + HasPrivateCompute::Type // Results in TrueType + HasValue // Is derived from TrueType + HasEvaluate::value // Evaluates to 'false' + HasDetermine::Type // Results in FalseType + HasData // 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, Base, TYPE1230 >::Type \ + , Fallback \ + {}; \ + \ + template < typename U > \ + static No& test( Check* ); \ + \ + template < typename U > \ + static Yes& test( ... ); \ + \ + public: \ + enum : bool { value = ( sizeof( test( nullptr ) ) == sizeof( Yes ) ) }; \ +}; \ + \ +template< typename TYPE1230 > \ +struct TYPE_TRAIT_NAME \ + : public blaze::BoolConstant< TYPE_TRAIT_NAME##HELPER::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::value // Evaluates to 'true' + HasProtectedType::Type // Results in TrueType + HasPrivateType // Is derived from TrueType + HasValueType::value // Evaluates to 'false' + HasElementType::Type // Results in FalseType + HasDataType // 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, 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( nullptr ) ) == sizeof( Yes ) ) }; \ +}; \ + \ +template< typename TYPE1231 > \ +struct TYPE_TRAIT_NAME \ + : public blaze::BoolConstant< TYPE_TRAIT_NAME##HELPER::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::value // Evaluates to 'true' + HasProtectedType::Type // Results in TrueType + HasValue // Is derived from TrueType + HasPublicType::value // Evaluates to 'false' + HasDetermine::Type // Results in FalseType + HasData // 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::value || \ + LOCAL_TYPE_TRAIT_2::value ); \ +}; \ + \ +template< typename Type1232 > \ +struct TYPE_TRAIT_NAME \ + : public blaze::BoolConstant< TYPE_TRAIT_NAME##HELPER::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 +#include + + +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::value // Evaluates to 'true' (on most architectures) + blaze::HasSize::Type // Results in TrueType (on most architectures) + blaze::HasSize // Is derived from TrueType (on most architectures) + blaze::HasSize::value // Evaluates to 'false' + blaze::HasSize::Type // Results in FalseType + blaze::HasSize // 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 : 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 : 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 : 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 : 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::value // Evaluates to 'true' (on most architectures) + blaze::Has1Byte::Type // Results in TrueType (on most architectures) + blaze::Has1Byte // Is derived from TrueType (on most architectures) + blaze::Has1Byte::value // Evaluates to 'false' + blaze::Has1Byte::Type // Results in FalseType + blaze::Has1Byte // Is derived from FalseType + \endcode +*/ +template< typename T > +struct Has1Byte : public HasSize +{}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// 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::value // Evaluates to 'true' (on most architectures) + blaze::Has2Bytes::Type // Results in TrueType (on most architectures) + blaze::Has2Bytes // Is derived from TrueType (on most architectures) + blaze::Has2Bytes::value // Evaluates to 'false' + blaze::Has2Bytes::Type // Results in FalseType + blaze::Has2Bytes // Is derived from FalseType + \endcode +*/ +template< typename T > +struct Has2Bytes : public HasSize +{}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// 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::value // Evaluates to 'true' (on most architectures) + blaze::Has4Bytes::Type // Results in TrueType (on most architectures) + blaze::Has4Bytes // Is derived from TrueType (on most architectures) + blaze::Has4Bytes::value // Evaluates to 'false' + blaze::Has4Bytes::Type // Results in FalseType + blaze::Has4Bytes // Is derived from FalseType + \endcode +*/ +template< typename T > +struct Has4Bytes : public HasSize +{}; +//************************************************************************************************* + + + + +//================================================================================================= +// +// 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::value // Evaluates to 'true' (on most architectures) + blaze::Has8Bytes::Type // Results in TrueType (on most architectures) + blaze::Has8Bytes // Is derived from TrueType (on most architectures) + blaze::Has8Bytes::value // Evaluates to 'false' + blaze::Has8Bytes::Type // Results in FalseType + blaze::Has8Bytes // Is derived from FalseType + \endcode +*/ +template< typename T > +struct Has8Bytes : public HasSize +{}; +//************************************************************************************************* + +} // 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 +#include +#include + + +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::value // Evaluates to 'true' + blaze::HaveSameSize::Type // Results in TrueType + blaze::HaveSameSize // Is derived from TrueType + blaze::HaveSameSize::value // Evalutes to 'false' + blaze::HaveSameSize::Type // Results in FalseType + blaze::HaveSameSize // 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 : 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 : 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 : 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 +#include + + +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::value // Evaluates to 'true' + blaze::IsArithmetic::Type // Results in TrueType + blaze::IsArithmetic // Is derived from TrueType + blaze::IsArithmetic::value // Evaluates to 'false' + blaze::IsArithmetic::value // Evaluates to 'false' + blaze::IsArithmetic::Type // Results in FalseType + blaze::IsArithmetic // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsArithmetic : public BoolConstant< std::is_arithmetic::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 +#include + + +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 > // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsArray : public BoolConstant< std::is_array::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 +#include + + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Compile time type check. +// \ingroup type_traits +// +// The IsAssignable type trait tests whether the expression + + \code + std::declval() = std::declval(); + \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::value > +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time type check. +// \ingroup type_traits +// +// The IsNothrowAssignable type trait tests whether the expression + + \code + std::declval() = std::declval(); + \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::value > +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time type check. +// \ingroup type_traits +// +// The IsCopyAssignable type trait tests whether the expression + + \code + std::declval() = std::declval(); + \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::value > +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time type check. +// \ingroup type_traits +// +// The IsNothrowCopyAssignable type trait tests whether the expression + + \code + std::declval() = std::declval(); + \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::value > +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time type check. +// \ingroup type_traits +// +// The IsMoveAssignable type trait tests whether the expression + + \code + std::declval() = std::move( std::declval() ); + \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::value > +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time type check. +// \ingroup type_traits +// +// The IsNothrowMoveAssignable type trait tests whether the expression + + \code + std::declval() = std::move( std::declval() ); + \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::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 +#include +#include + + +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::value // Evaluates to 'true' + blaze::IsBaseOf::Type // Results in TrueType + blaze::IsBaseOf // Is derived from TrueType + blaze::IsBaseOf::value // Evaluates to 'false' + blaze::IsBaseOf::Type // Results in FalseType + blaze::IsBaseOf // Is derived from FalseType + \endcode +*/ +template< typename Base, typename Derived > +class IsBaseOf : public BoolConstant< std::is_base_of< RemoveCV_, RemoveCV_ >::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsBoolean::Type // Results in TrueType + blaze::IsBoolean // Is derived from TrueType + blaze::IsBoolean::value // Evaluates to 'false' (float is not a boolean) + blaze::IsBoolean::Type // Results in FalseType + blaze::IsBoolean // 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 : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsBoolean type trait for 'const bool'. +template<> +struct IsBoolean : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsBoolean type trait for 'volatile bool'. +template<> +struct IsBoolean : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsBoolean type trait for 'const volatile bool' +template<> +struct IsBoolean : 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 +#include + + +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::value // Evaluates to 'true' + blaze::IsBuiltin::Type // Results in TrueType + blaze::IsBuiltin // Is derived from TrueType + blaze::IsBuiltin::value // Evaluates to 'false' + blaze::IsBuiltin::Type // Results in FalseType + blaze::IsBuiltin // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsBuiltin : public BoolConstant< std::is_fundamental::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsCharacter::Type // Results in TrueType + blaze::IsCharacter // Is derived from TrueType + blaze::IsCharacter::value // Evaluates to 'false' + blaze::IsCharacter::Type // Results in FalseType + blaze::IsCharacter // 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 : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsCharacter type trait for the plain 'signed char' type. +template<> +struct IsCharacter : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsCharacter type trait for the plain 'unsigned char' type. +template<> +struct IsCharacter : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsCharacter type trait for the plain 'wchar_t' type. +template<> +struct IsCharacter : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Partial specialization of the IsCharacter type trait 'const' qualified types. +template< typename T > +struct IsCharacter : public IsCharacter::Type +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Partial specialization of the IsCharacter type trait 'volatile' qualified types. +template< typename T > +struct IsCharacter : public IsCharacter::Type +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Partial specialization of the IsCharacter type trait 'const volatile' types. +template< typename T > +struct IsCharacter : public IsCharacter::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsClass::Type // Results in TrueType + blaze::IsClass // Is derived from TrueType + blaze::IsClass::value // Evaluates to 'false' (int is a built-in data type) + blaze::IsClass::Type // Results in FalseType + blaze::IsClass // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsClass : public BoolConstant< std::is_class::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 +#include +#include + + +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 >::value // Evaluates to 'true' + blaze::IsComplex< const complex >::Type // Results in TrueType + blaze::IsComplex< volatile complex > // 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 > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsComplex type trait for 'const complex'. +template< typename T > +struct IsComplex< const complex > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsComplex type trait for 'volatile complex'. +template< typename T > +struct IsComplex< volatile complex > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsComplex type trait for 'const volatile complex' +template< typename T > +struct IsComplex< const volatile complex > : 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 +#include +#include + + +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. +// In case the type is \c complex (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 >::value // Evaluates to 'true' + blaze::IsComplexDouble< const complex >::Type // Results in TrueType + blaze::IsComplexDouble< volatile complex > // Is derived from TrueType + blaze::IsComplexDouble< double >::value // Evaluates to 'false' + blaze::IsComplexDouble< const complex >::Type // Results in FalseType + blaze::IsComplexDouble< const volatile complex > // 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' type. +template<> +struct IsComplexDouble< complex > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsComplexDouble type trait for 'const complex'. +template<> +struct IsComplexDouble< const complex > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsComplexDouble type trait for 'volatile complex'. +template<> +struct IsComplexDouble< volatile complex > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsComplexDouble type trait for 'const volatile complex' +template<> +struct IsComplexDouble< const volatile complex > : 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 +#include +#include + + +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. +// In case the type is \c complex (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 >::value // Evaluates to 'true' + blaze::IsComplexFloat< const complex >::Type // Results in TrueType + blaze::IsComplexFloat< volatile complex > // Is derived from TrueType + blaze::IsComplexFloat< float >::value // Evaluates to 'false' + blaze::IsComplexFloat< const complex >::Type // Results in FalseType + blaze::IsComplexFloat< const volatile complex > // 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' type. +template<> +struct IsComplexFloat< complex > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsComplexFloat type trait for 'const complex'. +template<> +struct IsComplexFloat< const complex > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsComplexFloat type trait for 'volatile complex'. +template<> +struct IsComplexFloat< volatile complex > : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsComplexFloat type trait for 'const volatile complex' +template<> +struct IsComplexFloat< const volatile complex > : 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 +#include + + +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::value // Evaluates to 'true' + blaze::IsConst::Type // Results in TrueType + blaze::IsConst // Is derived from TrueType + blaze::IsConst::value // Evaluates to 'false' + blaze::IsConst::Type // Results in FalseType (the const-qualifier is not at the top level) + blaze::IsConst // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsConst : public BoolConstant< std::is_const::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 +#include + + +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()... ); + \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::value > +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time type check. +// \ingroup type_traits +// +// The IsNothrowConstructible type trait tests whether the expression + + \code + T obj( std::declval()... ); + \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::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::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::value > +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time type check. +// \ingroup type_traits +// +// The IsCopyConstructible type trait tests whether the expression + + \code + T obj( std::declval() ); + \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::value > +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time type check. +// \ingroup type_traits +// +// The IsNothrowCopyConstructible type trait tests whether the expression + + \code + T obj( std::declval() ); + \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::value > +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time type check. +// \ingroup type_traits +// +// The IsMoveConstructible type trait tests whether the expression + + \code + T obj( std::move( std::declval() ) ); + \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::value > +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time type check. +// \ingroup type_traits +// +// The IsNothrowMoveConstructible type trait tests whether the expression + + \code + T obj( std::move( std::declval() ) ); + \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::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsConvertible::value // Evaluates to 'true' + blaze::IsConvertible::Type // Results in TrueType + blaze::IsConvertible::Type // Results in TrueType + blaze::IsConvertible // Is derived from TrueType + blaze::IsConvertible // Is derived from TrueType + blaze::IsConvertible::value // Evaluates to 'false' + blaze::IsConvertible::Type // Results in FalseType + blaze::IsConvertible // Is derived from FalseType + \endcode +*/ +template< typename From, typename To > +struct IsConvertible : public BoolConstant< std::is_convertible::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 +#include + + +namespace blaze { + +//================================================================================================= +// +// CLASS DEFINITIONS +// +//================================================================================================= + +//************************************************************************************************* +/*!\brief Compile time type check. +// \ingroup type_traits +// +// The IsDestructible type trait tests whether the expression + + \code + std::declval().~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::value > +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*!\brief Compile time type check. +// \ingroup type_traits +// +// The IsDestructible type trait tests whether the expression + + \code + std::declval().~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::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsDouble::Type // Results in TrueType + blaze::IsDouble // Is derived from TrueType + blaze::IsDouble::value // Evaluates to 'false' + blaze::IsDouble::Type // Results in FalseType + blaze::IsDouble // 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 : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsDouble type trait for 'const double'. +template<> +struct IsDouble : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsDouble type trait for 'volatile double'. +template<> +struct IsDouble : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsDouble type trait for 'const volatile double'. +template<> +struct IsDouble : 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 +#include + + +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::value // Evaluates to 'true' + blaze::IsEmpty::Type // Results in TrueType + blaze::IsEmpty // Is derived from TrueType + blaze::IsEmpty::value // Evaluates to 'false' + blaze::IsEmpty::Type // Results in FalseType + blaze::IsEmpty // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsEmpty : public BoolConstant< std::is_empty::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsFloat::Type // Results in TrueType + blaze::IsFloat // Is derived from TrueType + blaze::IsFloat::value // Evaluates to 'false' + blaze::IsFloat::Type // Results in FalseType + blaze::IsFloat // 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 : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsFloat type trait for 'const float'. +template<> +struct IsFloat : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsFloat type trait for 'volatile float'. +template<> +struct IsFloat : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsFloat type trait for 'const volatile float'. +template<> +struct IsFloat : 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 +#include + + +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::value // Evaluates to 'true' + blaze::IsFloatingPoint::Type // Result in TrueType + blaze::IsFloatingPoint // Is derived from TrueType + blaze::IsFloatingPoint::value // Evaluates to 'false' + blaze::IsFloatingPoint::Type // Results in FalseType + blaze::IsFloatingPoint // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsFloatingPoint : public BoolConstant< std::is_floating_point::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsInteger::Type // Results in TrueType + blaze::IsInteger // Is derived from TrueType + blaze::IsInteger::value // Evaluates to 'false' + blaze::IsInteger::Type // Results in FalseType + blaze::IsInteger // 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 : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsInteger type trait for 'const int'. +template<> +struct IsInteger : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsInteger type trait for 'volatile int'. +template<> +struct IsInteger : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsInteger type trait for 'const volatile int'. +template<> +struct IsInteger : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsInteger type trait for the plain 'unsigned int' type. +template<> +struct IsInteger : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsInteger type trait for 'const unsigned int'. +template<> +struct IsInteger : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsInteger type trait for 'volatile unsigned int'. +template<> +struct IsInteger : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsInteger type trait for 'const volatile unsigned int'. +template<> +struct IsInteger : 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 +#include + + +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::value // Evaluates to 'true' + blaze::IsIntegral::Type // Results in TrueType (char is an integral data type) + blaze::IsIntegral // Is derived from TrueType + blaze::IsIntegral::value // Evaluates to 'false' + blaze::IsIntegral::Type // Results in FalseType + blaze::IsIntegral // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsIntegral : public BoolConstant< std::is_integral::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsLong::Type // Results in TrueType + blaze::IsLong // Is derived from TrueType + blaze::IsLong::value // Evaluates to 'false' + blaze::IsLong::Type // Results in FalseType + blaze::IsLong // 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 : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsLong type trait for 'const long'. +template<> +struct IsLong : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsLong type trait for 'volatile long'. +template<> +struct IsLong : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsLong type trait for 'const volatile long'. +template<> +struct IsLong : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsLong type trait for the plain 'unsigned long' type. +template<> +struct IsLong : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsLong type trait for 'const unsigned long'. +template<> +struct IsLong : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsLong type trait for 'volatile unsigned long'. +template<> +struct IsLong : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsLong type trait for 'const volatile unsigned long'. +template<> +struct IsLong : 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 +#include + + +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::value // Evaluates to 'true' + blaze::IsLongDouble::Type // Results in TrueType + blaze::IsLongDouble // Is derived from TrueType + blaze::IsLongDouble::value // Evaluates to 'false' + blaze::IsLongDouble::Type // Results in FalseType + blaze::IsLongDouble // 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 : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsLongDouble type trait for 'const long double'. +template<> +struct IsLongDouble : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsLongDouble type trait for 'volatile long double'. +template<> +struct IsLongDouble : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsLongDouble type trait for 'const volatile long double'. +template<> +struct IsLongDouble : 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 +#include +#include +#include +#include + + +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::value // Evaluates to 'true' (int is a numeric data type) + blaze::IsNumeric::Type // Results in TrueType (float is a numeric data type) + blaze::IsNumeric > // Is derived from TrueType (complex is a numeric data type) + blaze::IsNumeric::value // Evaluates to 'false' (void is not a numeric data type) + blaze::IsNumeric::Type // Results in FalseType (bool is not a numeric data type) + blaze::IsNumeric // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsNumeric : public BoolConstant< IsBuiltin::value && !IsBoolean::value && !IsVoid::value > +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsNumeric type trait for the plain 'complex' type. +template< typename T > +struct IsNumeric< complex > : public IsNumeric::Type +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsNumeric type trait for 'const complex'. +template< typename T > +struct IsNumeric< const complex > : public IsNumeric::Type +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsNumeric type trait for 'volatile complex'. +template< typename T > +struct IsNumeric< volatile complex > : public IsNumeric::Type +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsNumeric type trait for 'const volatile complex'. +template< typename T > +struct IsNumeric< const volatile complex > : public IsNumeric::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsObject::Type // Results in TrueType + blaze::IsObject // Is derived from TrueType + blaze::IsObject // Also derived from TrueType + blaze::IsObject::value // Evaluates to 'false' + blaze::IsObject::Type // Results in FalseType + blaze::IsObject // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsObject : public BoolConstant< std::is_object::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsPod::Type // Results in TrueType + blaze::IsPod // Is derived from TrueType + blaze::IsPod< std::vector >::value // Evaluates to 'false' + blaze::IsPod::Type // Results in FalseType + blaze::IsPod // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsPod : public BoolConstant< std::is_pod::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsPointer::Type // Results in TrueType + blaze::IsPointer // Is derived from TrueType + blaze::IsPointer::value // Evaluates to 'false' + blaze::IsPointer::Type // Results in FalseType + blaze::IsPointer // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsPointer : public BoolConstant< std::is_pointer::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsReference::Type // Results in TrueType + blaze::IsReference // Is derived from TrueType + blaze::IsReference::value // Evaluates to 'false' + blaze::IsReference::Type // Results in FalseType + blaze::IsReference // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsReference : public BoolConstant< std::is_reference::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 +#include +#include +#include + + +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::value // Evaluates to 'true' + blaze::IsStrictlySame::Type // Results in TrueType + blaze::IsStrictlySame // Is derived from TrueType + blaze::IsStrictlySame::value // Evaluates to 'false' + blaze::IsStrictlySame::Type // Results in FalseType + blaze::IsStrictlySame // 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 : 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_, RemoveCV_ >::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::value // Evaluates to 'true' + blaze::IsSame::Type // Results in TrueType + blaze::IsSame // Is derived from TrueType + blaze::IsSame::value // Evaluates to 'false' + blaze::IsSame::Type // Results in FalseType + blaze::IsSame // Is derived from FalseType + \endcode +*/ +template< typename A, typename B > +struct IsSame : public BoolConstant< IsSameHelper::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsShort::Type // Results in TrueType + blaze::IsShort // Is derived from TrueType + blaze::IsShort::value // Evaluates to 'false' + blaze::IsShort::Type // Results in FalseType + blaze::IsShort // 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 : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsShort type trait for 'const short'. +template<> +struct IsShort : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsShort type trait for 'volatile short'. +template<> +struct IsShort : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsShort type trait for 'const volatile short'. +template<> +struct IsShort : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsShort type trait for the plain 'unsigned short' type. +template<> +struct IsShort : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsShort type trait for 'const unsigned short'. +template<> +struct IsShort : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsShort type trait for 'volatile unsigned short'. +template<> +struct IsShort : public TrueType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsShort type trait for 'const volatile unsigned short'. +template<> +struct IsShort : 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 +#include + + +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::value // Evaluates to 'true' + blaze::IsSigned::Type // Results in TrueType + blaze::IsSigned // Is derived from TrueType + blaze::IsSigned::value // Evaluates to 'false' + blaze::IsSigned::Type // Results in FalseType + blaze::IsSigned // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsSigned : public BoolConstant< std::is_signed::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsUnion::Type // Results in TrueType + blaze::IsUnion // Is derived from TrueType + blaze::IsUnion::value // Evaluates to 'false' + blaze::IsUnion::Type // Results in FalseType + blaze::IsUnion // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsUnion : public BoolConstant< std::is_union::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsUnsigned::Type // Results in TrueType + blaze::IsUnsigned // Is derived from TrueType + blaze::IsUnsigned::value // Evaluates to 'false' + blaze::IsUnsigned::Type // Results in FalseType + blaze::IsUnsigned // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsUnsigned : public BoolConstant< std::is_unsigned::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 +#include +#include + + +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::value // Evaluates to 'true' + blaze::IsValid::Type // Results in TrueType + blaze::IsValid // Is derived from TrueType + blaze::IsValid::value // Evaluates to 'false' + blaze::IsValid::Type // Results in FalseType + blaze::IsValid // 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 : public FalseType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsValid type trait for 'const INVALID_TYPE'. +template<> +struct IsValid : public FalseType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsValid type trait for 'volatile INVALID_TYPE'. +template<> +struct IsValid : public FalseType +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the IsValid type trait for 'const volatile INVALID_TYPE'. +template<> +struct IsValid : 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 +#include +#include +#include +#include +#include + + +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, Complex, Builtin >::Type T2; + //********************************************************************************************** + + public: + //********************************************************************************************** + enum : bool { value = ( bool( BLAZE_SSE_MODE ) && IsFloat::value ) || + ( bool( BLAZE_SSE2_MODE ) && IsNumeric::value ) || + ( bool( BLAZE_MIC_MODE ) && IsNumeric::value && sizeof(T2) >= 4UL ) }; + //********************************************************************************************** +}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +/*!\brief Specialization of the IsVectorizableHelper class template for 'void'. +// \ingroup type_traits +*/ +template<> +struct IsVectorizableHelper +{ + 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_ >::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsVoid::Type // Results in TrueType + blaze::IsVoid // Is derived from TrueType + blaze::IsVoid::value // Evaluates to 'false' + blaze::IsVoid::Type // Results in FalseType + blaze::IsVoid // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsVoid : public BoolConstant< std::is_void::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 +#include + + +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::value // Evaluates to 'true' + blaze::IsVolatile::Type // Results in TrueType + blaze::IsVolatile // Is derived from TrueType + blaze::IsVolatile::value // Evaluates to 'false' (the volatile qualifier is not at the top level) + blaze::IsVolatile::Type // Results in FalseType + blaze::IsVolatile // Is derived from FalseType + \endcode +*/ +template< typename T > +struct IsVolatile : public BoolConstant< std::is_volatile::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 + + +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::Type // Results in 'int' + blaze::MakeSigned::Type // Results in 'const int' + blaze::MakeSigned::Type // Results in 'const long' + blaze::MakeSigned::Type // Signed integer type with the same width as the enum + blaze::MakeSigned::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::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::Type; + using Type2 = MakeSigned_; + \endcode +*/ +template< typename T > +using MakeSigned_ = typename MakeSigned::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 + + +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::Type // Results in 'unsigned int' + blaze::MakeUnsigned::Type // Results in 'const unsigned int' + blaze::MakeUnsigned::Type // Results in 'const unsigned long' + blaze::MakeUnsigned::Type // Unsigned integer type with the same width as the enum + blaze::MakeUnsigned::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::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::Type; + using Type2 = MakeUnsigned_; + \endcode +*/ +template< typename T > +using MakeUnsigned_ = typename MakeUnsigned::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 + + +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 >::value // Evaluates to 0 + \endcode +*/ +template< typename T > +struct Rank : public IntegralConstant +{}; +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the Rank type trait for empty arrays. +template< typename T > +struct Rank : public IntegralConstant::value> +{}; +/*! \endcond */ +//************************************************************************************************* + + +//************************************************************************************************* +/*! \cond BLAZE_INTERNAL */ +//! Specialization of the Rank type trait for non-empty arrays. +template< typename T, unsigned int N > +struct Rank : public IntegralConstant::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 + + +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::Type // Results in 'int' + blaze::RemoveAllExtents::Type // Results in 'int const' + blaze::RemoveAllExtents::Type // Results in 'int' + blaze::RemoveAllExtents::Type // Results in 'int' + blaze::RemoveAllExtents::Type // Results in 'int' + blaze::RemoveAllExtents::Type // Results in 'int const*' + \endcode +*/ +template< typename T > +struct RemoveAllExtents +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename std::remove_all_extents::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::Type; + using Type2 = RemoveAllExtents_; + \endcode +*/ +template< typename T > +using RemoveAllExtents_ = typename RemoveAllExtents::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 + + +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::Type // Results in 'short' + blaze::RemoveCV::Type // Results in 'double' + blaze::RemoveCV::Type // Results in 'float' + blaze::RemoveCV::Type // Results in 'int' + blaze::RemoveCV::Type // Results in 'int const*' + blaze::RemoveCV::Type // Results in 'int const*' + blaze::RemoveCV::Type // Results in 'int const&' + \endcode +*/ +template< typename T > +struct RemoveCV +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename std::remove_cv::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::Type; + using Type2 = RemoveCV_; + \endcode +*/ +template< typename T > +using RemoveCV_ = typename RemoveCV::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 + + +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::Type // Results in 'short' + blaze::RemoveConst::Type // Results in 'double' + blaze::RemoveConst::Type // Results in 'volatile int' + blaze::RemoveConst::Type // Results in 'const int*' + blaze::RemoveConst::Type // Results in 'const int*' + blaze::RemoveConst::Type // Results in 'const int&' + \endcode +*/ +template< typename T > +struct RemoveConst +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename std::remove_const::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::Type; + using Type2 = RemoveConst_; + \endcode +*/ +template< typename T > +using RemoveConst_ = typename RemoveConst::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 + + +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::Type // Results in 'int' + blaze::RemoveExtent::Type // Results in 'int const' + blaze::RemoveExtent::Type // Results in 'int[4]' + blaze::RemoveExtent::Type // Results in 'int[2]' + blaze::RemoveExtent::Type // Results in 'int const*' + \endcode +*/ +template< typename T > +struct RemoveExtent +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename std::remove_extent::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::Type; + using Type2 = RemoveExtent_; + \endcode +*/ +template< typename T > +using RemoveExtent_ = typename RemoveExtent::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 + + +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::Type // Results in 'int' + blaze::RemovePointer::Type // Results in 'const int' + blaze::RemovePointer::Type // Results in 'volatile int*' + blaze::RemovePointer::Type // Results in 'int&' + blaze::RemovePointer::Type // Results in 'int*&' + \endcode +*/ +template< typename T > +struct RemovePointer +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename std::remove_pointer::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::Type; + using Type2 = RemovePointer_; + \endcode +*/ +template< typename T > +using RemovePointer_ = typename RemovePointer::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 + + +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::Type // Results in 'int' + blaze::RemoveReference::Type // Results in 'const int' + blaze::RemoveReference::Type // Results in 'volatile int' + blaze::RemoveReference::Type // Results in 'int*' + blaze::RemoveReference::Type // Results in 'int*' + \endcode +*/ +template< typename T > +struct RemoveReference +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename std::remove_reference::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::Type; + using Type2 = RemoveReference_; + \endcode +*/ +template< typename T > +using RemoveReference_ = typename RemoveReference::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 + + +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::Type // Results in 'short' + blaze::RemoveVolatile::Type // Results in 'double' + blaze::RemoveVolatile::Type // Results in 'const int' + blaze::RemoveVolatile::Type // Results in 'int volatile*' + blaze::RemoveVolatile::Type // Results in 'int volatile*' + blaze::RemoveVolatile::Type // Results in 'int volatile&' + \endcode +*/ +template< typename T > +struct RemoveVolatile +{ + public: + //********************************************************************************************** + /*! \cond BLAZE_INTERNAL */ + typedef typename std::remove_volatile::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::Type; + using Type2 = RemoveVolatile_; + \endcode +*/ +template< typename T > +using RemoveVolatile_ = typename RemoveVolatile::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 + + +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 +#include +#include + + +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 : 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 + + +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 +#include +#include + + +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::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 : 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 : 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 Embeddings { + public: + Embeddings(const Weights& model) + : w_(model) + {} + + void Lookup(mblas::Matrix& Rows, const std::vector& ids) { + using namespace mblas; + std::vector tids = ids; + for(auto&& id : tids) + if(id >= w_.E_.rows()) + id = 1; + Rows = Assemble(w_.E_, tids); + } + + size_t GetCols() { + return w_.E_.columns(); + } + + size_t GetRows() const { + return w_.E_.rows(); + } + + private: + const Weights& w_; + }; + + ////////////////////////////////////////////////////////////// + template + 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(SourceContext); + Temp2_.resize(batchSize, SourceContext.columns()); + Temp2_ = 0.0f; + AddBiasVector(Temp2_, Temp1_); + + State = Temp2_ * w_.Wi_; + AddBiasVector(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 gru_; + + mblas::Matrix Temp1_; + mblas::Matrix Temp2_; + }; + + ////////////////////////////////////////////////////////////// + template + 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 gru_; + }; + + ////////////////////////////////////////////////////////////// + template + 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(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(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 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(T1_, w_.B1_); + AddBiasVector(T2_, w_.B2_); + AddBiasVector(T3_, w_.B3_); + + auto t = blaze::forEach(T1_ + T2_ + T3_, Tanh()); + + if(!filtered_) { + Probs_ = t * w_.W4_; + AddBiasVector(Probs_, w_.B4_); + } else { + Probs_ = t * FilteredW4_; + AddBiasVector(Probs_, FilteredB4_); + } + mblas::Softmax(Probs_); + Probs = blaze::forEach(Probs_, Log()); + } + + void Filter(const std::vector& ids) { + filtered_ = true; + using namespace mblas; + FilteredW4_ = Assemble(w_.W4_, ids); + FilteredB4_ = Assemble(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& w) { + embeddings_.Lookup(Embedding, w); + } + + void Filter(const std::vector& 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 embeddings_; + RNNHidden rnn1_; + RNNFinal rnn2_; + Attention attention_; + Softmax 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& words, + mblas::Matrix& context) { + std::vector 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 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 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 + 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 gru_; + + mblas::Matrix State_; + }; + + ///////////////////////////////////////////////////////////////// + public: + Encoder(const Weights& model) + : embeddings_(model.encEmbeddings_), + forwardRnn_(model.encForwardGRU_), + backwardRnn_(model.encBackwardGRU_) + {} + + void GetContext(const std::vector& words, + mblas::Matrix& context); + + private: + Embeddings embeddings_; + RNN forwardRnn_; + RNN 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 GRU { + public: + GRU(const Weights& model) + : w_(model) { + using namespace mblas; + WWx_ = Concat(w_.W_, w_.Wx_); + UUx_ = Concat(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 &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(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(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 +#include +#include + +#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 &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 +#include +#include + +#include "../blaze/Math.h" +#include "phoenix_functions.h" + +namespace mblas { + +typedef blaze::DynamicMatrix Matrix; +typedef blaze::DynamicVector Vector; +typedef blaze::DynamicVector ColumnVector; + +template +class BlazeMatrix : public blaze::CustomMatrix { + public: + typedef T value_type; + typedef typename std::vector::iterator iterator; + typedef typename std::vector::const_iterator const_iterator; + typedef blaze::CustomMatrix 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 + 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& operator=(const value_type& val) { + *(BlazeBase*)this = val; + return *this; + } + + template + BlazeMatrix& 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& rhs) { + std::swap(data_, rhs.data_); + std::swap(static_cast(*this), static_cast(rhs)); + } + + private: + std::vector data_; +}; + +typedef BlazeMatrix ArrayMatrix; + +template +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 +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 +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 +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 +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 RowPair; +typedef std::vector RowPairs; +typedef std::vector DeviceRowPairs; + +const bool byRow = true; +const bool byColumn = false; + +template +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 +MT Assemble(const MT1& in, + const std::vector& 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 +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 +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 +#include + +#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 + inline T operator()(T val) const { + return expapprox(val); + } + }; + + struct Log { + template + inline T operator()(T val) const { + return logapprox(val); + } + }; + + struct Logit { + template + inline T operator()(T val) const { + return logitapprox(val); + } + }; + + struct Tanh { + template + 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 + +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 +#include + +#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 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_; +};