diff --git a/src/amdis/common/CMakeLists.txt b/src/amdis/common/CMakeLists.txt index 8988200e608707affde9dd38d09769b8b4139b63..89f2d370f56993ad5dc3eb2d6d9541797220dd09 100644 --- a/src/amdis/common/CMakeLists.txt +++ b/src/amdis/common/CMakeLists.txt @@ -22,6 +22,7 @@ install(FILES MultiTypeMatrix.hpp MultiTypeVector.hpp Range.hpp + Resize.hpp StaticSize.hpp String.hpp Tags.hpp diff --git a/src/amdis/common/Resize.hpp b/src/amdis/common/Resize.hpp new file mode 100644 index 0000000000000000000000000000000000000000..a94b71c9fdf9572d9dde83dc97c1c0a2445a0804 --- /dev/null +++ b/src/amdis/common/Resize.hpp @@ -0,0 +1,124 @@ +#pragma once + +#include <dune/common/typeutilities.hh> + +#include <amdis/common/ConceptsBase.hpp> +#include <amdis/common/Logical.hpp> + +namespace AMDiS +{ + namespace Concepts + { + namespace Definition + { + struct VectorResizable + { + template <class V> + auto requires_(V const& vec, Dune::PriorityTag<2>) -> decltype( const_cast<V&>(vec).resize(0u), 0); + + template <class V> + auto requires_(V const& vec, Dune::PriorityTag<1>) -> decltype( const_cast<V&>(vec).change_dim(0u), 0); + }; + + struct MatrixResizable + { + template <class M> + auto requires_(M const& mat, Dune::PriorityTag<3>) -> decltype( const_cast<M&>(mat).resize(0u,0u), 0); + + template <class M> + auto requires_(M const& mat, Dune::PriorityTag<2>) -> decltype( const_cast<M&>(mat).change_dim(0u,0u), 0); + + template <class M> + auto requires_(M const& mat, Dune::PriorityTag<1>) -> decltype( const_cast<M&>(mat).setSize(0u,0u), 0); + }; + } + + /// Checks whether a vector can be resized by various resize methods + template <class Vector> + using VectorResizable_t = bool_t<models<Definition::VectorResizable(Vector, Dune::PriorityTag<42>)> >; + + /// Checks whether a matrix can be resized by various resize methods + template <class Matrix> + using MatrixResizable_t = bool_t<models<Definition::MatrixResizable(Matrix, Dune::PriorityTag<42>)> >; + + } // end namespace Concepts + +#ifdef DOXYGEN + /// \brief Uniform vector resize, using either vector.resize() or vector.change_dim() + template <class Vector> + void resize(Vector& vec, std::size_t size); + + /// \brief Uniform matrix resize, using either matrix.resize(), matrix.setSize() or matrix.change_dim() + template <class Matrix> + void resize(Matrix& mat, std::size_t r, std::size_t c); +#else + + namespace Impl + { + template <class Vector, + class = void_t<decltype(std::declval<Vector&>().resize(0u))> > + void resize_impl(Vector& vec, std::size_t size, Dune::PriorityTag<2>) + { + vec.resize(size); + } + + template <class Vector, + class = void_t<decltype(std::declval<Vector&>().change_dim(0u))> > + void resize_impl(Vector& vec, std::size_t size, Dune::PriorityTag<1>) + { + vec.change_dim(size); + } + + template <class Vector> + void resize_impl(Vector& /*vec*/, std::size_t /*size*/, Dune::PriorityTag<0>) + { + /* do nothing */ + } + } + + template <class Vector> + void resize(Vector& vec, std::size_t size) + { + Impl::resize_impl(vec, size, Dune::PriorityTag<42>{}); + } + + + namespace Impl + { + template <class Matrix, + class = void_t<decltype(std::declval<Matrix&>().resize(0u,0u))> > + void resize_impl(Matrix& mat, std::size_t rows, std::size_t cols, Dune::PriorityTag<3>) + { + mat.resize(rows, cols); + } + + template <class Matrix, + class = void_t<decltype(std::declval<Matrix&>().change_dim(0u,0u))> > + void resize_impl(Matrix& mat, std::size_t rows, std::size_t cols, Dune::PriorityTag<2>) + { + mat.change_dim(rows, cols); + } + + template <class Matrix, + class = void_t<decltype(std::declval<Matrix&>().setSize(0u,0u))> > + void resize_impl(Matrix& mat, std::size_t rows, std::size_t cols, Dune::PriorityTag<1>) + { + mat.setSize(rows, cols); + } + + template <class Matrix> + void resize_impl(Matrix& /*mat*/, std::size_t /*rows*/, std::size_t /*cols*/, Dune::PriorityTag<0>) + { + /* do nothing */ + } + } + + template <class Matrix> + void resize(Matrix& mat, std::size_t rows, std::size_t cols) + { + Impl::resize_impl(mat, rows, cols, Dune::PriorityTag<42>{}); + } + +#endif + +} // end namespace AMDiS diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 175d7be627869f12af9355290e39d7a485ecf104..82bc31b7a3f9b06f6c17f75c590d8e96bff22789 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -61,6 +61,9 @@ dune_add_test(SOURCES ProblemStatTest.cpp dune_add_test(SOURCES RangeTypeTest.cpp LINK_LIBRARIES amdis) +dune_add_test(SOURCES ResizeTest.cpp + LINK_LIBRARIES amdis) + dune_add_test(SOURCES StringTest.cpp LINK_LIBRARIES amdis) diff --git a/test/ResizeTest.cpp b/test/ResizeTest.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f6f0511d6f471f06decaeae7ac13bbc8be632fb4 --- /dev/null +++ b/test/ResizeTest.cpp @@ -0,0 +1,65 @@ +#include <amdis/AMDiS.hpp> +#include <amdis/common/Resize.hpp> + +using namespace AMDiS; + +struct Vec1 { void resize(std::size_t) {} }; +struct Vec2 { void change_dim(std::size_t) {} }; +struct Vec3 +{ + void resize(std::size_t) {} + void change_dim(std::size_t) {} +}; + +struct Mat1 { void resize(std::size_t,std::size_t) {} }; +struct Mat2 { void change_dim(std::size_t,std::size_t) {} }; +struct Mat3 { void setSize(std::size_t,std::size_t) {} }; +struct Mat4 +{ + void resize(std::size_t,std::size_t) {} + void change_dim(std::size_t,std::size_t) {} + void setSize(std::size_t,std::size_t) {} +}; + +struct NotResizable {}; + +int main(int argc, char** argv) +{ + Environment env(argc, argv); + + Vec1 vec1; + Vec2 vec2; + Vec3 vec3; + + resize(vec1, 1); + resize(vec2, 1); + resize(vec3, 1); + + static_assert(Concepts::VectorResizable_t<Vec1>::value, ""); + static_assert(Concepts::VectorResizable_t<Vec2>::value, ""); + static_assert(Concepts::VectorResizable_t<Vec3>::value, ""); + + Mat1 mat1; + Mat2 mat2; + Mat3 mat3; + Mat4 mat4; + + resize(mat1,1,1); + resize(mat2,1,1); + resize(mat3,1,1); + resize(mat4,1,1); + + static_assert(Concepts::MatrixResizable_t<Mat1>::value, ""); + static_assert(Concepts::MatrixResizable_t<Mat2>::value, ""); + static_assert(Concepts::MatrixResizable_t<Mat3>::value, ""); + static_assert(Concepts::MatrixResizable_t<Mat4>::value, ""); + + NotResizable notResizable; + resize(notResizable,1); + resize(notResizable,1,1); + + static_assert(not Concepts::VectorResizable_t<NotResizable>::value, ""); + static_assert(not Concepts::MatrixResizable_t<NotResizable>::value, ""); + + return 0; +}