diff --git a/include/El/blas_like/level1/Dot.hpp b/include/El/blas_like/level1/Dot.hpp index beda613785..ce1dc6fdde 100644 --- a/include/El/blas_like/level1/Dot.hpp +++ b/include/El/blas_like/level1/Dot.hpp @@ -19,7 +19,7 @@ T Dot( const Matrix& A, const Matrix& B ) } template -T Dot( const ElementalMatrix& A, const ElementalMatrix& B ) +T Dot( const AbstractDistMatrix& A, const AbstractDistMatrix& B ) { EL_DEBUG_CSE return HilbertSchmidt( A, B ); @@ -114,7 +114,7 @@ T Dotu( const DistMultiVec& A, const DistMultiVec& B ) EL_EXTERN template T Dot \ ( const Matrix& A, const Matrix& B ); \ EL_EXTERN template T Dot \ - ( const ElementalMatrix& A, const ElementalMatrix& B ); \ + ( const AbstractDistMatrix& A, const AbstractDistMatrix& B ); \ EL_EXTERN template T Dot \ ( const DistMultiVec& A, const DistMultiVec& B ); \ EL_EXTERN template T Dotu \ diff --git a/include/El/blas_like/level1/Hadamard.hpp b/include/El/blas_like/level1/Hadamard.hpp index e1a5b062d2..89ff1c52b7 100644 --- a/include/El/blas_like/level1/Hadamard.hpp +++ b/include/El/blas_like/level1/Hadamard.hpp @@ -42,9 +42,9 @@ void Hadamard( const Matrix& A, const Matrix& B, Matrix& C ) template void Hadamard -( const ElementalMatrix& A, - const ElementalMatrix& B, - ElementalMatrix& C ) +( const AbstractDistMatrix& A, + const AbstractDistMatrix& B, + AbstractDistMatrix& C ) { EL_DEBUG_CSE const DistData& ADistData = A.DistData(); @@ -60,6 +60,9 @@ void Hadamard LogicError("A, B, and C must share the same distribution"); if( A.ColAlign() != B.ColAlign() || A.RowAlign() != B.RowAlign() ) LogicError("A and B must be aligned"); + if ( A.BlockHeight() != B.BlockHeight() || + A.BlockWidth() != B.BlockWidth()) + LogicError("A and B must have the same block size"); C.AlignWith( A.DistData() ); C.Resize( A.Height(), A.Width() ); Hadamard( A.LockedMatrix(), B.LockedMatrix(), C.Matrix() ); @@ -87,9 +90,9 @@ void Hadamard EL_EXTERN template void Hadamard \ ( const Matrix& A, const Matrix& B, Matrix& C ); \ EL_EXTERN template void Hadamard \ - ( const ElementalMatrix& A, \ - const ElementalMatrix& B, \ - ElementalMatrix& C ); \ + ( const AbstractDistMatrix& A, \ + const AbstractDistMatrix& B, \ + AbstractDistMatrix& C ); \ EL_EXTERN template void Hadamard \ ( const DistMultiVec& A, \ const DistMultiVec& B, \ diff --git a/include/El/blas_like/level1/decl.hpp b/include/El/blas_like/level1/decl.hpp index 48cd5f269e..e129c0968b 100644 --- a/include/El/blas_like/level1/decl.hpp +++ b/include/El/blas_like/level1/decl.hpp @@ -196,9 +196,9 @@ void Recv( Matrix& A, mpi::Comm comm, int source ); template void ColumnTwoNorms ( const Matrix& X, Matrix>& norms ); -template +template void ColumnTwoNorms -( const DistMatrix& X, DistMatrix,V,STAR>& norms ); +( const DistMatrix& X, DistMatrix,V,STAR,W>& norms ); template void ColumnTwoNorms ( const DistMultiVec& X, Matrix>& norms ); @@ -235,9 +235,9 @@ void ColumnTwoNorms template void ColumnMaxNorms ( const Matrix& X, Matrix>& norms ); -template +template void ColumnMaxNorms -( const DistMatrix& X, DistMatrix,V,STAR>& norms ); +( const DistMatrix& X, DistMatrix,V,STAR,W>& norms ); template void ColumnMaxNorms ( const DistMultiVec& X, Matrix>& norms ); @@ -802,7 +802,7 @@ void DiagonalSolve template T Dot( const Matrix& A, const Matrix& B ); template -T Dot( const ElementalMatrix& A, const ElementalMatrix& B ); +T Dot( const AbstractDistMatrix& A, const AbstractDistMatrix& B ); template T Dot( const DistMultiVec& A, const DistMultiVec& B ); @@ -1155,9 +1155,9 @@ template void Hadamard( const Matrix& A, const Matrix& B, Matrix& C ); template void Hadamard -( const ElementalMatrix& A, - const ElementalMatrix& B, - ElementalMatrix& C ); +( const AbstractDistMatrix& A, + const AbstractDistMatrix& B, + AbstractDistMatrix& C ); template void Hadamard ( const DistMultiVec& A, @@ -1170,7 +1170,7 @@ template T HilbertSchmidt( const Matrix& A, const Matrix& B ); template T HilbertSchmidt -( const ElementalMatrix& A, const ElementalMatrix& C ); +( const AbstractDistMatrix& A, const AbstractDistMatrix& C ); template T HilbertSchmidt( const DistMultiVec& A, const DistMultiVec& B ); diff --git a/src/blas_like/level1/ColumnNorms.cpp b/src/blas_like/level1/ColumnNorms.cpp index 05bfc21b6a..9ac43012f6 100644 --- a/src/blas_like/level1/ColumnNorms.cpp +++ b/src/blas_like/level1/ColumnNorms.cpp @@ -103,9 +103,9 @@ void ColumnMaxNorms( const Matrix& X, Matrix>& norms ) } } -template +template void ColumnTwoNorms -( const DistMatrix& A, DistMatrix,V,STAR>& norms ) +( const DistMatrix& A, DistMatrix,V,STAR,W>& norms ) { EL_DEBUG_CSE norms.AlignWith( A ); @@ -118,9 +118,9 @@ void ColumnTwoNorms ColumnTwoNormsHelper( A.LockedMatrix(), norms.Matrix(), A.ColComm() ); } -template +template void ColumnMaxNorms -( const DistMatrix& A, DistMatrix,V,STAR>& norms ) +( const DistMatrix& A, DistMatrix,V,STAR,W>& norms ) { EL_DEBUG_CSE norms.AlignWith( A ); @@ -363,11 +363,17 @@ void ColumnTwoNorms #define PROTO_DIST(Field,U,V) \ template void ColumnTwoNorms \ - ( const DistMatrix& X, \ - DistMatrix,V,STAR>& norms ); \ + ( const DistMatrix& X, \ + DistMatrix,V,STAR,ELEMENT>& norms ); \ template void ColumnMaxNorms \ - ( const DistMatrix& X, \ - DistMatrix,V,STAR>& norms ); + ( const DistMatrix& X, \ + DistMatrix,V,STAR,ELEMENT>& norms ); \ + template void ColumnTwoNorms \ + ( const DistMatrix& X, \ + DistMatrix,V,STAR,BLOCK>& norms ); \ + template void ColumnMaxNorms \ + ( const DistMatrix& X, \ + DistMatrix,V,STAR,BLOCK>& norms ); #define PROTO(Field) \ template void ColumnTwoNorms \ diff --git a/src/blas_like/level1/HilbertSchmidt.cpp b/src/blas_like/level1/HilbertSchmidt.cpp index 65dd1e7be3..ca7f2c3685 100644 --- a/src/blas_like/level1/HilbertSchmidt.cpp +++ b/src/blas_like/level1/HilbertSchmidt.cpp @@ -41,7 +41,7 @@ Ring HilbertSchmidt( const Matrix& A, const Matrix& B ) template Ring HilbertSchmidt -( const ElementalMatrix& A, const ElementalMatrix& B ) +( const AbstractDistMatrix& A, const AbstractDistMatrix& B ) { EL_DEBUG_CSE if( A.Height() != B.Height() || A.Width() != B.Width() ) @@ -53,6 +53,9 @@ Ring HilbertSchmidt LogicError("A and B must have the same distribution"); if( A.ColAlign() != B.ColAlign() || A.RowAlign() != B.RowAlign() ) LogicError("Matrices must be aligned"); + if ( A.BlockHeight() != B.BlockHeight() || + A.BlockWidth() != B.BlockWidth()) + LogicError("A and B must have the same block size"); Ring innerProd; if( A.Participating() ) @@ -112,7 +115,7 @@ Ring HilbertSchmidt( const DistMultiVec& A, const DistMultiVec& B ) template Ring HilbertSchmidt \ ( const Matrix& A, const Matrix& B ); \ template Ring HilbertSchmidt \ - ( const ElementalMatrix& A, const ElementalMatrix& B ); \ + ( const AbstractDistMatrix& A, const AbstractDistMatrix& B ); \ template Ring HilbertSchmidt \ ( const DistMultiVec& A, const DistMultiVec& B ); diff --git a/tests/blas_like/ColumnNorms.cpp b/tests/blas_like/ColumnNorms.cpp new file mode 100644 index 0000000000..6d91fa0e97 --- /dev/null +++ b/tests/blas_like/ColumnNorms.cpp @@ -0,0 +1,134 @@ +/* + Copyright (c) 2009-2016, Jack Poulson + All rights reserved. + + This file is part of Elemental and is under the BSD 2-Clause License, + which can be found in the LICENSE file in the root directory, or at + http://opensource.org/licenses/BSD-2-Clause +*/ + +#include +using namespace El; + +template +void TestColumnTwoNorms(Int m, Int n, const Grid& g, bool print) +{ + // Generate random matrix to test. + DistMatrix A(g); + Uniform(A, m, n); + if (print) + Print(A, "A"); + DistMatrix norms(g); + ColumnTwoNorms(A, norms); + if (print) + Print(norms, "norms"); + for (Int j = 0; j < A.LocalWidth(); ++j) + { + T got = norms.GetLocal(j, 0); + T expected = 0; + for (Int i = 0; i < A.LocalHeight(); ++i) + { + T val = A.GetLocal(i, j); + expected += val * val; + } + expected = mpi::AllReduce(expected, g.ColComm()); + expected = Sqrt(expected); + // Compute max(expected, 1) to use relative bound. + // (std::max and El::Max don't support BigFloat. + T div = expected > 1 ? expected : 1; + if (Abs(got - expected) / div > m * n * 10 * limits::Epsilon>()) + { + Output("Results do not match, norms(", j, ")=", got, + " instead of ", expected); + RuntimeError("got != expected"); + } + } +} + +template +void TestColumnMaxNorms(Int m, Int n, const Grid& g, bool print) +{ + // Generate random matrix to test. + DistMatrix A(g); + Uniform(A, m, n); + if (print) + Print(A, "A"); + DistMatrix norms(g); + ColumnMaxNorms(A, norms); + if (print) + Print(norms, "norms"); + for (Int j = 0; j < A.LocalWidth(); ++j) + { + T got = norms.GetLocal(j, 0); + T expected = 0; + for (Int i = 0; i < A.LocalHeight(); ++i) + expected = Max(expected, Abs(A.GetLocal(i, j))); + T r; + mpi::AllReduce(&expected, &r, 1, mpi::MAX, g.ColComm()); + expected = r; + if (got != expected) + { + Output("Results do not match, norms(", j, ")=", got, + " instead of ", expected); + RuntimeError("got != expected"); + } + } +} + +int main(int argc, char** argv) +{ + Environment env(argc, argv); + mpi::Comm comm = mpi::COMM_WORLD; + try + { + const Int m = Input("--m", "height", 100); + const Int n = Input("--n", "width", 100); + const bool print = Input("--print", "print matrices?", false); + ProcessInput(); + PrintInputReport(); + + const Grid g(comm); + OutputFromRoot(comm, "Testing ColumnTwoNorms"); + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); +#if defined(EL_HAVE_QD) + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); +#endif +#if defined(EL_HAVE_QUAD) + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); +#endif +#if defined(EL_HAVE_MPC) + TestColumnTwoNorms(m, n, g, print); + TestColumnTwoNorms(m, n, g, print); +#endif + OutputFromRoot(comm, "Testing ColumnMaxNorms"); + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); +#if defined(EL_HAVE_QD) + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); +#endif +#if defined(EL_HAVE_QUAD) + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); +#endif +#if defined(EL_HAVE_MPC) + TestColumnMaxNorms(m, n, g, print); + TestColumnMaxNorms(m, n, g, print); +#endif + } + catch (exception& e) + { + ReportException(e); + } +} diff --git a/tests/blas_like/Dot.cpp b/tests/blas_like/Dot.cpp new file mode 100644 index 0000000000..6ba62857ad --- /dev/null +++ b/tests/blas_like/Dot.cpp @@ -0,0 +1,95 @@ +/* + Copyright (c) 2009-2016, Jack Poulson + All rights reserved. + + This file is part of Elemental and is under the BSD 2-Clause License, + which can be found in the LICENSE file in the root directory, or at + http://opensource.org/licenses/BSD-2-Clause +*/ + +#include +using namespace El; + +template +void TestDot(Int m, Int n, const Grid& g, bool print) +{ + // Generate random matrices to test. + DistMatrix A(g); + Uniform(A, m, n); + DistMatrix B(g); + Uniform(B, m, n); + if (print) + { + Print(A, "A"); + Print(B, "B"); + } + // Do Dot. + T got = Dot(A, B); + if (print) + OutputFromRoot(g.Comm(), "result=", got); + // Manually check results. + T expected = 0; + for (Int j = 0; j < A.LocalWidth(); ++j) + for (Int i = 0; i < B.LocalHeight(); ++i) + expected += Conj(A.GetLocal(i, j)) * B.GetLocal(i, j); + expected = mpi::AllReduce(expected, g.Comm()); + // The constant here is large because this is not an especially stable way + // to compute the dot product, but it provides a dumb implementation baseline. + if (Abs(got - expected) > 700 * limits::Epsilon>()) + { + Output("Results do not match, got=", got, + " instead of ", expected); + RuntimeError("got != expected"); + } +} + +int main(int argc, char** argv) +{ + Environment env(argc, argv); + mpi::Comm comm = mpi::COMM_WORLD; + try + { + const Int m = Input("--m", "height", 100); + const Int n = Input("--n", "width", 100); + const bool print = Input("--print", "print matrices?", false); + ProcessInput(); + PrintInputReport(); + + const Grid g(comm); + OutputFromRoot(comm, "Testing Dot"); + TestDot(m, n, g, print); + TestDot(m, n, g, print); + TestDot, ELEMENT>(m, n, g, print); + TestDot, BLOCK>(m, n, g, print); + TestDot(m, n, g, print); + TestDot(m, n, g, print); + TestDot, ELEMENT>(m, n, g, print); + TestDot, BLOCK>(m, n, g, print); +#if defined(EL_HAVE_QD) + TestDot(m, n, g, print); + TestDot(m, n, g, print); + TestDot, ELEMENT>(m, n, g, print); + TestDot, BLOCK>(m, n, g, print); + TestDot(m, n, g, print); + TestDot(m, n, g, print); + TestDot, ELEMENT>(m, n, g, print); + TestDot, BLOCK>(m, n, g, print); +#endif +#if defined(EL_HAVE_QUAD) + TestDot(m, n, g, print); + TestDot(m, n, g, print); + TestDot, ELEMENT>(m, n, g, print); + TestDot, BLOCK>(m, n, g, print); +#endif +#if defined(EL_HAVE_MPC) + TestDot(m, n, g, print); + TestDot(m, n, g, print); + TestDot, ELEMENT>(m, n, g, print); + TestDot, BLOCK>(m, n, g, print); +#endif + } + catch (exception& e) + { + ReportException(e); + } +} diff --git a/tests/blas_like/Hadamard.cpp b/tests/blas_like/Hadamard.cpp new file mode 100644 index 0000000000..0af0fa6468 --- /dev/null +++ b/tests/blas_like/Hadamard.cpp @@ -0,0 +1,98 @@ +/* + Copyright (c) 2009-2016, Jack Poulson + All rights reserved. + + This file is part of Elemental and is under the BSD 2-Clause License, + which can be found in the LICENSE file in the root directory, or at + http://opensource.org/licenses/BSD-2-Clause +*/ + +#include +using namespace El; + +template +void TestHadamard(Int m, Int n, const Grid& g, bool print) +{ + // Generate random matrices to test. + DistMatrix A(g); + Uniform(A, m, n); + DistMatrix B(g); + Uniform(B, m, n); + if (print) + { + Print(A, "A"); + Print(B, "B"); + } + // Apply Hadamard. + DistMatrix C(g); + Hadamard(A, B, C); + mpi::Barrier(g.Comm()); + if (print) + Print(C, "C"); + // Manually check results. + for (Int j = 0; j < A.LocalWidth(); ++j) + { + for (Int i = 0; i < A.LocalHeight(); ++i) + { + T got = C.GetLocal(i, j); + T expected = A.GetLocal(i, j) * B.GetLocal(i, j); + if (Abs(got - expected) > 10 * limits::Epsilon>()) + { + Output("Results do not match, C(", i, ",", j, ")=", got, + " instead of ", expected); + RuntimeError("got != expected"); + } + } + } +} + +int main(int argc, char** argv) +{ + Environment env(argc, argv); + mpi::Comm comm = mpi::COMM_WORLD; + try + { + const Int m = Input("--m", "height", 100); + const Int n = Input("--n", "width", 100); + const bool print = Input("--print", "print matrices?", false); + ProcessInput(); + PrintInputReport(); + + const Grid g(comm); + OutputFromRoot(comm, "Testing Hadamard"); + TestHadamard(m, n, g, print); + TestHadamard(m, n, g, print); + TestHadamard, ELEMENT>(m, n, g, print); + TestHadamard, BLOCK>(m, n, g, print); + TestHadamard(m, n, g, print); + TestHadamard(m, n, g, print); + TestHadamard, ELEMENT>(m, n, g, print); + TestHadamard, BLOCK>(m, n, g, print); +#if defined(EL_HAVE_QD) + TestHadamard(m, n, g, print); + TestHadamard(m, n, g, print); + TestHadamard, ELEMENT>(m, n, g, print); + TestHadamard, BLOCK>(m, n, g, print); + TestHadamard(m, n, g, print); + TestHadamard(m, n, g, print); + TestHadamard, ELEMENT>(m, n, g, print); + TestHadamard, BLOCK>(m, n, g, print); +#endif +#if defined(EL_HAVE_QUAD) + TestHadamard(m, n, g, print); + TestHadamard(m, n, g, print); + TestHadamard, ELEMENT>(m, n, g, print); + TestHadamard, BLOCK>(m, n, g, print); +#endif +#if defined(EL_HAVE_MPC) + TestHadamard(m, n, g, print); + TestHadamard(m, n, g, print); + TestHadamard, ELEMENT>(m, n, g, print); + TestHadamard, BLOCK>(m, n, g, print); +#endif + } + catch (exception& e) + { + ReportException(e); + } +}