|
24 | 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
25 | 25 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
26 | 26 | DEALINGS IN THE SOFTWARE. |
| 27 | + |
| 28 | + Author : Moritz Dannhauer (reimplementation) |
| 29 | + Date: August 2017 |
27 | 30 | */ |
28 | 31 |
|
29 | 32 | #include <Core/Algorithms/Math/AppendMatrix.h> |
30 | 33 | #include <Core/Datatypes/DenseMatrix.h> |
| 34 | +#include <Core/Datatypes/SparseRowMatrix.h> |
| 35 | +#include <Core/Datatypes/SparseRowMatrixFromMap.h> |
| 36 | +#include <Core/Datatypes/Legacy/Matrix/MatrixOperations.h> |
31 | 37 | #include <Core/Algorithms/Base/AlgorithmVariableNames.h> |
| 38 | +#include <Core/Datatypes/MatrixTypeConversions.h> |
| 39 | +#include <Eigen/Sparse> |
32 | 40 |
|
33 | 41 | using namespace SCIRun::Core::Algorithms; |
34 | 42 | using namespace SCIRun::Core::Algorithms::Math; |
35 | 43 | using namespace SCIRun::Core::Datatypes; |
36 | 44 |
|
| 45 | +const AlgorithmInputName AppendMatrixAlgorithm::InputMatrices("InputMatrices"); |
| 46 | + |
37 | 47 | AppendMatrixAlgorithm::AppendMatrixAlgorithm() |
38 | 48 | { |
39 | 49 | addParameter(Variables::RowsOrColumns, 0); |
40 | 50 | } |
41 | 51 |
|
42 | | -AppendMatrixAlgorithm::Outputs AppendMatrixAlgorithm::run(const AppendMatrixAlgorithm::Inputs& input, const AppendMatrixAlgorithm::Parameters& params) const |
| 52 | + |
| 53 | +bool AppendMatrixAlgorithm::check_dimensions(const Matrix& mat1, const Matrix& mat2, const AppendMatrixAlgorithm::Parameters& params) const |
43 | 54 | { |
44 | | - DenseMatrixConstHandle lhsPtr = input.get<0>(); |
45 | | - DenseMatrixConstHandle rhsPtr = input.get<1>(); |
46 | | - if (!lhsPtr || !rhsPtr) |
47 | | - return Outputs(); /// @todo: error |
| 55 | + auto rows_m1=mat1.nrows(),rows_m2=mat2.nrows(),cols_m1=mat1.ncols(),cols_m2=mat2.ncols(); |
| 56 | + if (params == ROWS) |
| 57 | + { |
| 58 | + if(cols_m1!=cols_m2) return false; |
| 59 | + } else |
| 60 | + if(rows_m1!=rows_m2) return false; |
| 61 | + |
| 62 | + return true; |
| 63 | +} |
| 64 | + |
| 65 | +AppendMatrixAlgorithm::Outputs AppendMatrixAlgorithm::ConcatenateMatrices(const MatrixHandle base_matrix, const std::vector<boost::shared_ptr<Matrix>> input_matrices, const AppendMatrixAlgorithm::Parameters& params) const |
| 66 | +{ |
48 | 67 |
|
49 | | - const DenseMatrix& lhs = *lhsPtr; |
50 | | - const DenseMatrix& rhs = *rhsPtr; |
| 68 | + if (input_matrices.size()==0) |
| 69 | + return base_matrix; |
| 70 | + |
| 71 | + Outputs outputs = run(boost::make_tuple(base_matrix, input_matrices[0]), params); |
| 72 | + for(Eigen::Index c=1; c<input_matrices.size(); c++) |
| 73 | + { |
| 74 | + auto concatenated = run(boost::make_tuple(outputs, input_matrices[c]), params); |
| 75 | + outputs=concatenated; |
| 76 | + } |
| 77 | + |
| 78 | + return outputs; |
| 79 | +} |
51 | 80 |
|
52 | | - if (params == ROWS) |
| 81 | +AppendMatrixAlgorithm::Outputs AppendMatrixAlgorithm::run(const AppendMatrixAlgorithm::Inputs& input, const AppendMatrixAlgorithm::Parameters& params) const |
| 82 | +{ |
| 83 | + auto lhsPtr = input.get<0>(); |
| 84 | + auto rhsPtr = input.get<1>(); |
| 85 | + if (!lhsPtr || !rhsPtr) |
| 86 | + error(" At least two matrices are needed to run this module. "); |
| 87 | + |
| 88 | + if (!((matrixIs::sparse(lhsPtr) && matrixIs::sparse(rhsPtr)) || (matrixIs::dense(lhsPtr) && matrixIs::dense(rhsPtr)) || (matrixIs::column(lhsPtr) && matrixIs::column(rhsPtr)))) |
53 | 89 | { |
54 | | - if (lhs.cols() != rhs.cols()) |
55 | | - return Outputs(); /// @todo: error |
56 | | - |
57 | | - DenseMatrixHandle output(boost::make_shared<DenseMatrix>(lhs.rows() + rhs.rows(), lhs.cols())); |
58 | | - for (int i = 0; i < lhs.rows(); ++i) |
59 | | - for (int j = 0; j < lhs.cols(); ++j) |
60 | | - (*output)(i,j) = lhs(i,j); |
61 | | - for (int i = 0; i < rhs.rows(); ++i) |
62 | | - for (int j = 0; j < rhs.cols(); ++j) |
63 | | - (*output)(i + lhs.rows(), j) = rhs(i,j); |
64 | | - return output; |
| 90 | + error(" Mixing of different matrix types as inputs is not supported. "); |
| 91 | + return Outputs(); |
65 | 92 | } |
66 | | - else // columns |
| 93 | + |
| 94 | + if (!check_dimensions(*lhsPtr, *rhsPtr, params)) |
67 | 95 | { |
68 | | - if (lhs.rows() != rhs.rows()) |
69 | | - return Outputs(); /// @todo: error |
70 | | - |
71 | | - DenseMatrixHandle output(boost::make_shared<DenseMatrix>(lhs.rows(), lhs.cols() + rhs.cols())); |
72 | | - for (int i = 0; i < lhs.rows(); ++i) |
73 | | - for (int j = 0; j < lhs.cols(); ++j) |
74 | | - (*output)(i,j) = lhs(i,j); |
75 | | - for (int i = 0; i < rhs.rows(); ++i) |
76 | | - for (int j = 0; j < rhs.cols(); ++j) |
77 | | - (*output)(i, j + lhs.cols()) = rhs(i,j); |
78 | | - return output; |
| 96 | + error(" Input matrix dimensions do not match. "); |
| 97 | + return Outputs(); |
79 | 98 | } |
| 99 | + |
| 100 | + Eigen::MatrixXd result; |
| 101 | + if(matrixIs::dense(lhsPtr) || matrixIs::column(lhsPtr)) |
| 102 | + { |
| 103 | + if(params == ROWS) |
| 104 | + result=Eigen::MatrixXd(lhsPtr->nrows()+rhsPtr->nrows(),lhsPtr->ncols()); |
| 105 | + else |
| 106 | + result=Eigen::MatrixXd(lhsPtr->nrows(),lhsPtr->ncols()+rhsPtr->ncols()); |
| 107 | + |
| 108 | + if(matrixIs::dense(lhsPtr)) |
| 109 | + result << *castMatrix::toDense(lhsPtr), *castMatrix::toDense(rhsPtr); |
| 110 | + else |
| 111 | + result << *castMatrix::toColumn(lhsPtr), *castMatrix::toColumn(rhsPtr); |
| 112 | + |
| 113 | + if (matrixIs::column(lhsPtr) && (result.rows()==1 || result.cols()==1)) |
| 114 | + return boost::make_shared<DenseColumnMatrix>(result); |
| 115 | + |
| 116 | + return boost::make_shared<DenseMatrix>(result); |
| 117 | + } else |
| 118 | + if (matrixIs::sparse(lhsPtr)) |
| 119 | + return SparseRowMatrixFromMap::concatenateSparseMatrices(*castMatrix::toSparse(lhsPtr),*castMatrix::toSparse(rhsPtr),params==ROWS); |
| 120 | + else |
| 121 | + { |
| 122 | + error(" This matrix type is not supported"); |
| 123 | + } |
| 124 | + |
| 125 | + return Outputs(); |
80 | 126 | } |
81 | 127 |
|
82 | 128 | AlgorithmOutput AppendMatrixAlgorithm::run(const AlgorithmInput& input) const |
83 | 129 | { |
84 | | - auto lhs = input.get<DenseMatrix>(Variables::FirstMatrix); |
85 | | - auto rhs = input.get<DenseMatrix>(Variables::SecondMatrix); |
86 | | - |
87 | | - auto outputs = run(boost::make_tuple(lhs, rhs), Option(get(Variables::RowsOrColumns).toInt())); |
88 | | - |
| 130 | + auto lhs = input.get<Matrix>(Variables::FirstMatrix); |
| 131 | + auto rhs = input.get<Matrix>(Variables::SecondMatrix); |
| 132 | + auto input_matrices = input.getList<Matrix>(AppendMatrixAlgorithm::InputMatrices); |
| 133 | + |
| 134 | + Outputs outputs; |
| 135 | + Parameters params=Option(get(Variables::RowsOrColumns).toInt()); |
| 136 | + outputs = run(boost::make_tuple(lhs, rhs), params); |
| 137 | + |
| 138 | + if (input_matrices.size()>0) |
| 139 | + outputs = ConcatenateMatrices(outputs, input_matrices, params); |
| 140 | + |
89 | 141 | AlgorithmOutput output; |
90 | 142 | output[Variables::ResultMatrix] = outputs; |
91 | 143 | return output; |
|
0 commit comments