From 93dd050187b4add073c4ac0b16dacfeffdfea67e Mon Sep 17 00:00:00 2001 From: Christian Engwer <christi@dune-project.org> Date: Tue, 2 Aug 2005 12:24:59 +0000 Subject: [PATCH] latest expression template updates [[Imported from SVN: r2502]] --- common/exprtmpl.hh | 505 +++++++++++++++++++++++++++++++++++++-- common/fmatrix.hh | 22 ++ common/test/.gitignore | 4 +- common/test/Makefile.am | 13 +- common/test/exprtmpl.cc | 512 +++++++++------------------------------- common/test/timing.cc | 107 +++++++++ istl/bcrsmatrix.hh | 24 ++ istl/bvector.hh | 7 +- 8 files changed, 771 insertions(+), 423 deletions(-) create mode 100644 common/test/timing.cc diff --git a/common/exprtmpl.hh b/common/exprtmpl.hh index 056ced1c8..a4964dc92 100644 --- a/common/exprtmpl.hh +++ b/common/exprtmpl.hh @@ -3,6 +3,22 @@ #ifndef DUNE_EXPRTMPL_HH #define DUNE_EXPRTMPL_HH +/* + This file is part of DUNE, a Distributed and Unified Numerics Environment + It is distributed under the terms of the GNU Lesser General Public License version 2.1 + See COPYING at the top of the source tree for the full licence. + */ + +/*! @file + + @brief This file provides expression templates for the + «Dense Matrix and Vector Template Library» and for the + «Iterative Solvers Template Library». + @verbatim + $Id$ + @endverbatim + */ + #include <iostream> #include <iomanip> #include <cstdlib> @@ -37,6 +53,11 @@ namespace Dune { template<class V> class FlatIterator; template<class K, int N> class FieldVector; + template<class K, int N, int M> class FieldMatrix; +#warning this header should not know about BCRSMatrix and BlockVector + class ISTLAllocator; + template<class B, class A=ISTLAllocator> class BCRSMatrix; + template<class B, class A=ISTLAllocator> class BlockVector; /** Type Traits for field_type and block_type @@ -63,13 +84,13 @@ namespace Dune { { typedef int type; }; - // FieldType specialization for FieldMatrix + // FieldType specialization for FieldVector template <class K, int N> struct FieldType< FieldVector<K,N> > { typedef K type; }; - // BlockType specialization for FieldMatrix + // BlockType specialization for FieldVector template <class K, int N> struct BlockType< FieldVector<K,N> > { @@ -77,15 +98,15 @@ namespace Dune { }; // FieldType specialization for const T template<class T> - struct BlockType<const T> + struct FieldType<const T> { - typedef const typename BlockType<T>::type type; + typedef const typename FieldType<T>::type type; }; // BlockType specialization for const T template<class T> - struct FieldType<const T> + struct BlockType<const T> { - typedef const typename FieldType<T>::type type; + typedef const typename BlockType<T>::type type; }; namespace ExprTmpl { @@ -95,6 +116,7 @@ namespace Dune { template <class Ex> class Expression; template <class A, class B, template<class> class Op> class ExBinOp; template <class I> class Vector; + template <class I> class Matrix; /** Type Trait for nested Expression @@ -196,8 +218,7 @@ namespace Dune { }; /** - 1 Dimensional Vector Base Class - for Glommable Expr1 Templates + Vector Base Class for Expression Templates */ template <class I> class Vector { @@ -266,25 +287,22 @@ namespace Dune { --INDENT; return asImp(); } -#if 0 -#warning rewrite these! template <class E> Vector<I>& operator+=(const Expression<E>& x) { - for (int i=0; i < asImp().N(); i++) asImp()[i] += x(i); + for (int i=0; i < asImp().N(); i++) asImp()[i] += x[i]; return asImp(); } template <class V> Vector<I>& operator+=(const Vector<V>& x) { - for (int i=0; i < asImp().N(); i++) asImp()[i] += x(i); + for (int i=0; i < asImp().N(); i++) asImp()[i] += x[i]; return asImp(); } template <class E> Vector<I>& operator-=(const Expression<E>& x) { - for (int i=0; i < asImp().N(); i++) asImp()[i] -= x(i); + for (int i=0; i < asImp().N(); i++) asImp()[i] -= x[i]; return asImp(); } template <class V> Vector<I>& operator-=(const Vector<V>& x) { - for (int i=0; i < asImp().N(); i++) asImp()[i] -= x(i); + for (int i=0; i < asImp().N(); i++) asImp()[i] -= x[i]; return asImp(); } -#endif Vector<I>& operator+=(field_type x) { for (int i=0; i < asImp().N(); i++) asImp()[i] += x; return asImp(); @@ -363,12 +381,463 @@ namespace Dune { typedef typename BlockType<I>::type type; }; - // --- + /** + Type Traits for row_type of Matrix + */ + template<class M> + struct RowType + { + typedef typename M::row_type type; + }; + template<class K, int N, int M> + struct RowType< FieldMatrix<K,N,M> > + { + typedef FieldVector<K,M> type; + }; + template <class I> + struct RowType< ExprTmpl::Matrix<I> > + { + typedef typename RowType<I>::type type; + }; + // RowType specialization for const T + template<class T> + struct RowType<const T> + { + typedef const typename RowType<T>::type type; + }; + + // Matrix-Vector Multiplication namespace ExprTmpl { - // --- + /** + Matrix Base Class for Expression Templates + */ + template <class I> + class Matrix { + public: + explicit Matrix() {} + typedef typename RowType<I>::type row_type; + typedef typename FieldType<I>::type field_type; + //! dimension of the vector space + int N() const { + return asImp().N(); + } + int M() const { + return asImp().M(); + } + row_type & operator[] (int i) { + return asImp()[i]; + } + const row_type & operator[] (int i) const { + return asImp()[i]; + } + private: + I & asImp() { return static_cast<I&>(*this); } + const I & asImp() const { return static_cast<const I&>(*this); } + }; + + // Trait Structs to extract infos needed for Matrix-Vector Multiplication + template<class M> + struct NestedDepth + { + enum { value = NestedDepth<typename BlockType<M>::type>::value + 1 }; + }; - } + template<class K, int N, int M> + struct NestedDepth< FieldMatrix<K,N,M> > + { + enum { value = 1 }; + }; + + template<class Me, class M> + struct MyDepth + { + enum { value = MyDepth<Me,typename BlockType<M>::type>::value+1 }; + }; + + template<class Me> + struct MyDepth<Me,Me> + { + enum { value = 0 }; + }; + + template<class B, int i> + struct BlockTypeN + { + typedef typename BlockTypeN<typename BlockType<B>::type, i-1>::type type; + }; + + template<class B> + struct BlockTypeN<B,0> + { + typedef B type; + }; + + template<class B> + struct BlockTypeN<B,-1> + { + typedef B type; + }; + + //! Type Traits for Vector::Iterator vs (const Vector)::ConstIterator + template<class T> + struct ColIteratorType + { + typedef typename T::ColIterator type; + }; + + template<class T> + struct ColIteratorType<const T> + { + typedef typename T::ConstColIterator type; + }; + + //! Iterator class for flat sequential access to a nested Matrix Row + template<class A> + class FlatColIterator : + public ForwardIteratorFacade<FlatColIterator<A>, + typename FieldType<A>::type, + typename FieldType<A>::type&, + int> + { + public: + typedef typename ColIteratorType<A>::type ColBlockIterator; + typedef std::ptrdiff_t DifferenceType; + // typedef typename BlockIterator::DifferenceType DifferenceType; + typedef typename BlockType<A>::type block_type; + typedef typename FieldType<A>::type field_type; + typedef FlatColIterator<block_type> SubBlockIterator; + FlatColIterator(const ColBlockIterator & i, const int* _M) : + M(_M), it(i), + bit((*i)[(*M)].begin(), M+1), + bend((*i)[(*M)].end(), M+1) {}; + void increment () + { + ++bit; + if (bit == bend) + { + ++it; + bit = (*it)[(*M)].begin(); + bend = (*it)[(*M)].end(); + } + } + bool equals (const FlatColIterator & fit) const + { + return fit.it == it && fit.bit == bit; + } + const field_type& dereference() const + { + return *bit; + } + template<class V> + const field_type& vectorentry(const Dune::ExprTmpl::Vector<V> & v) const + { + return bit.vectorentry(v[it.index()]); + } + //! return index + DifferenceType index () const + { + return bit.index(); + } + FlatColIterator operator = (const ColBlockIterator & _i) + { + it = _i; + bit = (*it)[(*M)].begin(); + bend = (*it)[(*M)].end(); + return *this; + } + private: + const int* M; + ColBlockIterator it; + SubBlockIterator bit; + SubBlockIterator bend; + }; + + template<class K, int N, int M> + class FlatColIterator<FieldMatrix<K,N,M> > : + public ForwardIteratorFacade< + FlatColIterator< FieldMatrix<K,N,M> >, K, K&, int> + { + public: + typedef + typename ColIteratorType< FieldMatrix<K,N,M> >::type ColBlockIterator; + typedef std::ptrdiff_t DifferenceType; + typedef K field_type; + FlatColIterator(const ColBlockIterator & i, const int*) : + it(i) {}; + void increment () + { + ++it; + } + bool equals (const FlatColIterator & fit) const + { + return fit.it == it; + } + field_type& dereference() const + { + return *it; + } + const field_type& vectorentry(const FieldVector<K,M> & v) const + { + return v[it.index()]; + } + //! return index + DifferenceType index () const + { + return it.index(); + } + FlatColIterator operator = (const ColBlockIterator & _i) + { + it = _i; + return *this; + } + private: + ColBlockIterator it; + }; + + template<class K, int N, int M> + class FlatColIterator<const FieldMatrix<K,N,M> > : + public ForwardIteratorFacade< + FlatColIterator< const FieldMatrix<K,N,M> >, const K, const K&, int> + { + public: + typedef + typename ColIteratorType< const FieldMatrix<K,N,M> >::type ColBlockIterator; + typedef std::ptrdiff_t DifferenceType; + typedef const K field_type; + FlatColIterator(const ColBlockIterator & i, const int*) : + it(i) {}; + void increment () + { + ++it; + } + bool equals (const FlatColIterator & fit) const + { + return fit.it == it; + } + field_type& dereference() const + { + return *it; + } + const field_type& vectorentry(const FieldVector<K,M> & v) const + { + return v[it.index()]; + } + //! return index + DifferenceType index () const + { + return it.index(); + } + FlatColIterator operator = (const ColBlockIterator & _i) + { + it = _i; + return *this; + } + private: + ColBlockIterator it; + }; + + /** + B: BlockMatrix type -> indicated the current level. + M: ,,global'' Matrix type + V: ,,global'' Vector type + */ + template <class B, class Mat, class Vec> + class MatrixMulVector + { + public: + typedef typename + BlockTypeN<MatrixMulVector<Mat,Mat,Vec>, MyDepth<B,Mat>::value-1>::type + ParentBlockType; + typedef + MatrixMulVector<typename BlockType<B>::type,Mat,Vec> SubMatrixMulVector; + typedef typename + Dune::ExprTmpl::BlockExpression< MatrixMulVector<B,Mat,Vec> >::type + BlockExpr; + typedef + typename BlockType<Mat>::type::ColIterator SubColIterator; + typedef typename Dune::FieldType<Vec>::type field_type; + /* constructor */ + MatrixMulVector(const Mat & _A, const Vec & _v, int* _M, + const ParentBlockType & _parent) : + parent(_parent), M(_M), A(_A), v(_v) {}; + BlockExpr operator[] (int i) const { + M[MyDepth<B,Mat>::value] = i; + return SubMatrixMulVector(A,v,M,*this); + } + int N() const { return -1; }; //r.begin()->N(); } + const ParentBlockType & parent; + private: + mutable int* M; + const Mat & A; + const Vec & v; + }; + + template <class Mat, class Vec> + class MatrixMulVector<Mat,Mat,Vec> + { + public: + typedef + MatrixMulVector<typename BlockType<Mat>::type,Mat,Vec> SubMatrixMulVector; + typedef + typename BlockType<Mat>::type::ColIterator SubColIterator; + typedef typename + Dune::ExprTmpl::BlockExpression< MatrixMulVector<Mat,Mat,Vec> >::type + BlockExpr; + typedef typename Dune::FieldType<Vec>::type field_type; + /* constructor */ + MatrixMulVector(const Mat & _A, const Vec & _v, int* _M) : + M(_M), A(_A), v(_v) {}; + BlockExpr operator[] (int i) const { + M[0] = i; + return SubMatrixMulVector(A,v,M,*this); + } + int N() const { return -1; }; // { parent.begin().N(); } + private: + mutable int* M; + const Mat & A; + const Vec & v; + }; + + template <class K, int iN, int iM, class Mat, class Vec> + class MatrixMulVector< FieldMatrix<K,iN,iM>, Mat, Vec > + { + public: + typedef typename + BlockTypeN<MatrixMulVector<Mat,Mat,Vec>, + MyDepth<FieldMatrix<K,iN,iM>,Mat>::value-1>::type + ParentBlockType; + /* constructor */ + MatrixMulVector(const Mat & _A, const Vec & _v, int* _M, + const ParentBlockType & _parent) : + parent(_parent), M(_M), A(_A), v(_v ) {}; + K operator[] (int i) const { + K x=0; + M[MyDepth<FieldMatrix<K,iN,iM>,Mat>::value] = i; + + FlatColIterator<const Mat> j(A[*M].begin(),M+1); + FlatColIterator<const Mat> endj(A[*M].end(),M+1); + for (; j!=endj; ++j) + { + x += (*j) * j.vectorentry(v); + } + return x; + } + int N() const { iN; }; + const ParentBlockType & parent; + private: + mutable int* M; + const Mat & A; + const Vec & v; + }; + + template <class K, int iN, int iM> + class MatrixMulVector< FieldMatrix<K,iN,iM>, FieldMatrix<K,iN,iM>, + FieldVector<K,iM> > + { + public: + typedef FieldMatrix<K,iN,iM> Mat; + typedef FieldVector<K,iM> Vec; + MatrixMulVector(const Mat & _A, const Vec & _v) : + A(_A), v(_v ){}; + K operator[] (int i) const { + K x=0; + typename Mat::ColIterator j = A[i].begin(); + typename Mat::ColIterator endj = A[i].end(); + for (; j!=endj; ++j) + { + x += (*j) * j.vectorentry(v); + } + return x; + } + int N() const { iN; }; + private: + const Mat & A; + const Vec & v; + }; + + template <class M, class A, class B> + struct BlockExpression< MatrixMulVector< M, A, B > > + { + typedef Expression< MatrixMulVector<typename BlockType<M>::type,A,B> > type; + }; + + template <class K, int N, int M, class A, class B> + struct BlockExpression< MatrixMulVector< FieldMatrix<K,N,M>, A, B > > + { + typedef K type; + }; + + template<class K, int N, int M> + ExprTmpl::Expression< + MatrixMulVector<FieldMatrix<K,N,M>, FieldMatrix<K,N,M>, FieldVector<K,M> > > + operator * ( const FieldMatrix<K,N,M> & A, const FieldVector<K,M> & v ) + { + return + ExprTmpl::Expression< + MatrixMulVector<FieldMatrix<K,N,M>, FieldMatrix<K,N,M>, FieldVector<K,M> > > + ( + MatrixMulVector<FieldMatrix<K,N,M>, FieldMatrix<K,N,M>, FieldVector<K,M> > + (A, v) + ); + } + + // template<class BM, class BV> + // ExprTmpl::Expression< + // MatrixMulVector<BCRSMatrix<BM>, BCRSMatrix<BM>, BlockVector<BV> > > + // operator * ( const BCRSMatrix<BM> & A, const BlockVector<BV> & v ) + // { + // static int indizes[20]; + // return + // Expression< + // MatrixMulVector<BCRSMatrix<BM>, BCRSMatrix<BM>, BlockVector<BV> > > + // ( + // MatrixMulVector<BCRSMatrix<BM>, BCRSMatrix<BM>, BlockVector<BV> >(A, v, indizes) + // ); + // } + + template<class M, class V> + ExprTmpl::Expression< + MatrixMulVector<Matrix<M>, Matrix<M>, Vector<V> > > + operator * ( const Matrix<M> & A, const Vector<V> & v ) + { + static int indizes[20]; + return + Expression< + MatrixMulVector<Matrix<M>, Matrix<M>, Vector<V> > > + ( + MatrixMulVector<Matrix<M>, Matrix<M>, Vector<V> >(A, v, indizes) + ); + } + + template<class I> + struct ColIteratorType< Matrix<I> > + { + typedef typename I::ColIterator type; + }; + template<class I> + struct ColIteratorType< const Matrix<I> > + { + typedef typename I::ConstColIterator type; + }; + + } // namespace ExprTmpl + + template <class B, class A, class V> + struct FieldType< ExprTmpl::MatrixMulVector<B,A,V> > + { + typedef typename FieldType<V>::type type; + }; + template <class I> + struct BlockType< ExprTmpl::Matrix<I> > + { + typedef typename BlockType<I>::type type; + }; + template <class I> + struct FieldType< ExprTmpl::Matrix<I> > + { + typedef typename FieldType<I>::type type; + }; // OPERATORS diff --git a/common/fmatrix.hh b/common/fmatrix.hh index 778303cd5..9f9480741 100644 --- a/common/fmatrix.hh +++ b/common/fmatrix.hh @@ -155,6 +155,7 @@ namespace Dune { fmmeta_umv<I-1>::template umv<Mat,X,Y,c>(A,x,y); } }; + template<> struct fmmeta_umv<0> { template<class Mat, class X, class Y, int c> @@ -502,8 +503,13 @@ namespace Dune { Implementation of all members uses template meta programs where appropriate */ +#ifdef DUNE_EXPRESSIONTEMPLATES + template<class K, int n, int m> + class FieldMatrix : ExprTmpl::Matrix< FieldMatrix<K,n,m> > +#else template<class K, int n, int m> class FieldMatrix +#endif { public: // standard constructor and everything is sufficient ... @@ -684,6 +690,9 @@ namespace Dune { if (y.N()!=N()) DUNE_THROW(FMatrixError,"index out of range"); #endif fmmeta_umv<n-1>::template umv<FieldMatrix,X,Y,m-1>(*this,x,y); + // for (int i=0; i<n; i++) + // for (int j=0; j<m; j++) + // y[i] += (*this)[i][j] * x[j]; } //! y += A^T x @@ -1417,6 +1426,19 @@ namespace Dune { } // end namespace FMatrixHelp +#ifdef DUNE_EXPRESSIONTEMPLATES + template <class K, int N, int M> + struct BlockType< FieldMatrix<K,N,M> > + { + typedef K type; + }; + + template <class K, int N, int M> + struct FieldType< FieldMatrix<K,N,M> > + { + typedef K type; + }; +#endif // DUNE_EXPRESSIONTEMPLATES /** @} end documentation */ diff --git a/common/test/.gitignore b/common/test/.gitignore index 14efccf9b..cc769b2c2 100644 --- a/common/test/.gitignore +++ b/common/test/.gitignore @@ -18,4 +18,6 @@ poolallocatortest gmon.out gcdlcdtest streamtest -exprtmpl \ No newline at end of file +exprtmpl +timing_xpr +timing_old \ No newline at end of file diff --git a/common/test/Makefile.am b/common/test/Makefile.am index b749532c5..db449a202 100644 --- a/common/test/Makefile.am +++ b/common/test/Makefile.am @@ -11,8 +11,9 @@ TESTS = $(TESTPROGS) check_PROGRAMS = $(TESTPROGS) # output code coverage -AM_CXXFLAGS = -fprofile-arcs -ftest-coverage -AM_LDFLAGS = $(top_builddir)/lib/libdune.la +#AM_CXXFLAGS = -fprofile-arcs -ftest-coverage +#AM_LDFLAGS = $(top_builddir)/lib/libdune.la +AM_LDFLAGS = $(top_builddir)/common/libcommon.la # define the programs @@ -42,9 +43,13 @@ settest_SOURCES=settest.cc gcdlcdtest_SOURCES = gcdlcdtest.cc +bin_PROGRAMS = exprtmpl timing_old timing_xpr exprtmpl_SOURCES = exprtmpl.cc -exprtmpl_CXXFLAGS = -DDUNE_EXPRESSIONTEMPLATES +exprtmpl_CXXFLAGS = -DDUNE_EXPRESSIONTEMPLATES -DNOPRINT # -DDUNE_ISTL_WITH_CHECKING -exprtmpl_LDFLAGS = $(top_builddir)/common/libcommon.la + +timing_old_SOURCES = timing.cc +timing_xpr_SOURCES = timing.cc +timing_xpr_CXXFLAGS = -DDUNE_EXPRESSIONTEMPLATES -g include $(top_srcdir)/am/global-rules diff --git a/common/test/exprtmpl.cc b/common/test/exprtmpl.cc index 0952fb79a..50b02c052 100644 --- a/common/test/exprtmpl.cc +++ b/common/test/exprtmpl.cc @@ -7,11 +7,14 @@ int *M; - fix RowBlock::N() - remove second template parameter of FlatColIterator + - vectorentry -> exrpressionentry + - FlatColIterator<Matrix> does not work if Matrix is mutable */ #include <iostream> #include <fstream> #include <dune/common/fvector.hh> +#include <dune/common/timer.hh> #include <dune/istl/bvector.hh> #include <dune/istl/io.hh> #include <dune/common/iteratorfacades.hh> @@ -58,11 +61,12 @@ void test_blockvector() void test_blockblockvector() { - typedef Dune::FieldVector<double,2> VB; + const int bs = 2; + const int sz = 3; + typedef Dune::FieldVector<double,bs> VB; typedef Dune::BlockVector<VB> BV; typedef Dune::BlockVector<BV> BBV; typedef Dune::ExprTmpl::ConstRef<BV> RBV; - const int sz = 3; BV bv1(sz), bv2(sz); bv1 = 1; bv2 = 0; @@ -77,6 +81,12 @@ void test_blockblockvector() bbv[0] = Dune::ExprTmpl::Expression<RBV>(rbv1); bbv[1].resize(bv2.N()); bbv[1] = Dune::ExprTmpl::Expression<RBV>(rbv2); + + Dune::Timer stopwatch; + stopwatch.reset(); + for (int i=0; i<100; i++) bbv *= 2; + std::cout << "Time bbv*2: " << stopwatch.elapsed() << std::endl; +#ifndef NOPRINT Dune::FlatIterator<BBV> fit(bbv.begin()); Dune::FlatIterator<BBV> fend(bbv.end()); int index = 0; @@ -90,380 +100,66 @@ void test_blockblockvector() printvector (std::cout, bv1, "bv1", "r"); printvector (std::cout, bv2, "bv1", "r"); printvector (std::cout, bbv, "bbv", "r"); -} - -namespace Dune { - - //! Type Traits for Vector::Iterator vs (const Vector)::ConstIterator - template<class T> - struct ColIteratorType - { - typedef typename T::ColIterator type; - }; - - template<class T> - struct ColIteratorType<const T> - { - typedef typename T::ConstColIterator type; - }; - - //! Iterator class for flat sequential access to a nested Matrix Row - template<class A, class V> - class FlatColIterator : - public ForwardIteratorFacade<FlatColIterator<A,V>, - typename FieldType<A>::type, - typename FieldType<A>::type&, - int> - { - public: - typedef typename ColIteratorType<A>::type ColBlockIterator; - typedef std::ptrdiff_t DifferenceType; - // typedef typename BlockIterator::DifferenceType DifferenceType; - typedef typename BlockType<A>::type block_type; - typedef typename BlockType<V>::type vblock_type; - typedef typename FieldType<A>::type field_type; - typedef FlatColIterator<block_type, vblock_type> SubBlockIterator; - FlatColIterator(const ColBlockIterator & i, const int* _M) : - M(_M), it(i), - bit((*i)[(*M)].begin(), M+1), - bend((*i)[(*M)].end(), M+1) {}; - void increment () - { - ++bit; - if (bit == bend) - { - ++it; - bit = (*it)[(*M)].begin(); - bend = (*it)[(*M)].end(); - } - } - bool equals (const FlatColIterator & fit) const - { - return fit.it == it && fit.bit == bit; - } - const field_type& dereference() const - { - return *bit; - } - const field_type& vectorentry(const V & v) const - { - return bit.vectorentry(v[it.index()]); - } - //! return index - DifferenceType index () const - { - return bit.index(); - } - FlatColIterator operator = (const ColBlockIterator & _i) - { - it = _i; - bit = (*it)[(*M)].begin(); - bend = (*it)[(*M)].end(); - return *this; - } - private: - const int* M; - ColBlockIterator it; - SubBlockIterator bit; - SubBlockIterator bend; - }; - - template<class K, int N, int M> - class FlatColIterator<FieldMatrix<K,N,M>, FieldVector<K,M> > : - public ForwardIteratorFacade< - FlatColIterator< FieldMatrix<K,N,M>, FieldVector<K,M> >, K, K&, int> - { - public: - typedef - typename ColIteratorType< FieldMatrix<K,N,M> >::type ColBlockIterator; - typedef std::ptrdiff_t DifferenceType; - typedef K field_type; - FlatColIterator(const ColBlockIterator & i, const int*) : - it(i) {}; - void increment () - { - ++it; - } - bool equals (const FlatColIterator & fit) const - { - return fit.it == it; - } - field_type& dereference() const - { - return *it; - } - const field_type& vectorentry(const FieldVector<K,M> & v) const - { - return v[it.index()]; - } - //! return index - DifferenceType index () const - { - return it.index(); - } - FlatColIterator operator = (const ColBlockIterator & _i) - { - it = _i; - return *this; - } - private: - ColBlockIterator it; - }; - - template<class K, int N, int M> - class FlatColIterator<const FieldMatrix<K,N,M>, const FieldVector<K,M> > : - public ForwardIteratorFacade< - FlatColIterator< const FieldMatrix<K,N,M>, const FieldVector<K,M> >, - const K, const K&, int> - { - public: - typedef - typename ColIteratorType< const FieldMatrix<K,N,M> >::type ColBlockIterator; - typedef std::ptrdiff_t DifferenceType; - typedef const K field_type; - FlatColIterator(const ColBlockIterator & i, const int*) : - it(i) {}; - void increment () - { - ++it; - } - bool equals (const FlatColIterator & fit) const - { - return fit.it == it; - } - field_type& dereference() const - { - return *it; - } - const field_type& vectorentry(const FieldVector<K,M> & v) const - { - return v[it.index()]; - } - //! return index - DifferenceType index () const - { - return it.index(); - } - FlatColIterator operator = (const ColBlockIterator & _i) - { - it = _i; - return *this; - } - private: - ColBlockIterator it; - }; - - template<class M> - struct NestedDepth - { - enum { value = NestedDepth<typename BlockType<M>::type>::value + 1 }; - }; - - template<class K, int N, int M> - struct NestedDepth< FieldMatrix<K,N,M> > - { - enum { value = 1 }; - }; - - template<class Me, class M> - struct MyDepth - { - enum { value = MyDepth<Me,typename BlockType<M>::type>::value+1 }; - }; - - template<class Me> - struct MyDepth<Me,Me> - { - enum { value = 0 }; - }; - - /** - B: BlockMatrix type -> indicated the current level. - M: ,,global'' Matrix type - V: ,,global'' Vector type - */ - template <class B, class Mat, class Vec> - class RowBlock - { - public: - typedef RowBlock<typename BlockType<B>::type,Mat,Vec> SubRowBlock; - typedef typename Dune::FieldType<Vec>::type field_type; - RowBlock(const Mat & _A, const Vec & _v, int* _M) : - M(_M), A(_A), v(_v) {}; - SubRowBlock operator[] (int i) const { - M[MyDepth<B,Mat>::value] = i; - return SubRowBlock(A,v,M); - } - int N() const { return -1; }; //r.begin()->N(); } - private: - mutable int* M; - const Mat & A; - const Vec & v; - }; - - // template <class K, int n, class M, class V> - // class BlockRowSum< FieldVector<K,n>, M, V > - template <class K, int iN, int iM, class Mat, class Vec> - class RowBlock< FieldMatrix<K,iN,iM>, Mat, Vec > - { - public: - RowBlock(const Mat & _A, const Vec & _v, int* _M) : - M(_M), A(_A), v(_v) {}; - K operator[] (int i) const { - K x=0; - M[MyDepth<FieldMatrix<K,iN,iM>,Mat>::value] = i; - - FlatColIterator<const Mat, const Vec> j(A[*M].begin(),M+1); - FlatColIterator<const Mat, const Vec> endj(A[*M].end(),M+1); - for (; j!=endj; ++j) - { - x += (*j) * j.vectorentry(v); - } - return x; - } - int N() const { return -1; }; //r.begin()->N(); } - private: - mutable int* M; - const Mat & A; - const Vec & v; - }; - - template <class M, class V> - class MV - { - public: - MV(const M & _A, const V & _v) : A(_A), v(_v) {}; - RowBlock<typename BlockType<M>::type,M,V> operator[] (int i) const { - indizes[0] = i; - return RowBlock<typename BlockType<M>::type,M,V>(A, v, indizes); - } - int N() const { return A.N(); } - private: - mutable int indizes[256]; - const M & A; - const V & v; - }; - - template <class K, int iM, int iN> - class MV< Dune::FieldMatrix<K,iN,iM>, Dune::FieldVector<K,iM> > - { - public: - typedef Dune::FieldMatrix<K,iN,iM> M; - typedef Dune::FieldVector<K,iM> V; - typedef typename Dune::FieldType<V>::type field_type; - MV(const M & _A, const V & _v) : A(_A), v(_v) {}; - field_type operator[] (int i) const { - std::cout << "ARGH\n"; - field_type x=0; - for (int j=0; j<iM; ++j) { - x += A[i][j] * v[j]; - } - return x; - } - int N() const { return A.N(); } - private: - const M & A; - const V & v; - }; - - template<class K, int N, int M> - ExprTmpl::Expression< MV< FieldMatrix<K,N,M>, FieldVector<K,M> > > - operator * ( const FieldMatrix<K,N,M> & A, const FieldVector<K,M> & v ) - { - return ExprTmpl::Expression< MV< FieldMatrix<K,N,M>, FieldVector<K,M> > > - ( MV< FieldMatrix<K,N,M>, FieldVector<K,M> > (A,v) ); - } - - template<class BM, class BV> - ExprTmpl::Expression< MV< BCRSMatrix<BM>, BlockVector<BV> > > - operator * ( const BCRSMatrix<BM> & A, const BlockVector<BV> & v ) - { - return ExprTmpl::Expression< MV< BCRSMatrix<BM>, BlockVector<BV> > > - ( MV< BCRSMatrix<BM>, BlockVector<BV> > (A,v) ); - } - - template <class A, class B> - struct FieldType< MV<A,B> > - { - typedef typename FieldType<B>::type type; - }; - - template <class B, class A, class V> - struct FieldType< RowBlock<B,A,V> > - { - typedef typename FieldType<V>::type type; - }; - - namespace ExprTmpl { - - template <class A, class B> - struct BlockExpression< MV< BCRSMatrix<A>,BlockVector<B> > > - { - typedef ExprTmpl::Expression< RowBlock< A, BCRSMatrix<A>,BlockVector<B> > > type; - }; - -#if 0 - // !TODO! - template <class A, class B> - struct BlockExpression< RowBlock< A, BCRSMatrix<A>,BlockVector<B> > > - { - typedef ExprTmpl::Expression< RowBlock< typename BlockType<A>::type, RowBlock< A, BCRSMatrix<A>,BlockVector<B> >,BlockVector<B> > > type; - }; #endif +} - template <class K, int N, int M, class A, class B> - struct BlockExpression< RowBlock< FieldMatrix<K,N,M>, A, B > > - { - typedef K type; - }; - - template <class K, int N, int M> - struct BlockExpression< MV< FieldMatrix<K,N,M>, FieldVector<K,M> > > - { - typedef K type; - }; - - } // NS ExpreTmpl - - template <class T> - struct BlockType< BCRSMatrix<T> > - { - typedef T type; - }; - - template <class K, int N, int M> - struct BlockType< FieldMatrix<K,N,M> > - { - typedef K type; - }; - - template <> - struct BlockType< double > - { - typedef double type; - }; - - template <class T> - struct FieldType< BCRSMatrix<T> > - { - typedef typename FieldType<T>::type type; - }; - - template <class K, int N, int M> - struct FieldType< FieldMatrix<K,N,M> > - { - typedef K type; - }; - -} // NS Dune - +// namespace Dune { + +// namespace ExprTmpl { + +// template <class K, int iN, int iM> +// class MatrixMulVector< FieldMatrix<K,iN,iM>, +// BCRSMatrix< FieldMatrix<K,iN,iM> >, +// BlockVector< FieldVector<K,iM> > > +// { +// public: +// typedef BCRSMatrix< FieldMatrix<K,iN,iM> > Mat; +// typedef BlockVector< FieldVector<K,iM> > Vec; +// typedef typename +// BlockTypeN<MatrixMulVector<Mat,Mat,Vec>, +// MyDepth<FieldMatrix<K,iN,iM>,Mat>::value-1>::type +// ParentBlockType; +// /* constructor */ +// MatrixMulVector(const Mat & _A, const Vec & _v, int* _M, +// const ParentBlockType & _parent) : +// parent(_parent), M(_M), A(_A), v(_v ) +// { +// int parent_i = M[0]; +// typename Mat::ConstColIterator it = A[parent_i].begin(); +// typename Mat::ConstColIterator end = A[parent_i].end(); +// tmp = 0; +// for (; it!=end; ++it) +// { +// it->umv(tmp,v[it.index()]); +// } +// }; +// K operator[] (int i) const { +// return tmp[i]; +// } +// int N() const { iN; }; +// const ParentBlockType & parent; +// private: +// FieldVector<K,iN> tmp; +// mutable int* M; +// const Mat & A; +// const Vec & v; +// }; + +// } // NS ExpreTmpl + +// } // NS Dune + +//template<int BlockSize, int N, int M> +template<int BN, int BM, int N, int M> void test_matrix() { - static const int BlockSize = 2; + std::cout << "test_matrix<" << BN << ", " << BM << ", " + << N << ", " << M << ">\n"; + typedef double matvec_t; - typedef Dune::FieldVector<matvec_t,BlockSize+1> VB; - typedef Dune::FieldVector<matvec_t,BlockSize> LVB; - typedef Dune::FieldMatrix<matvec_t,BlockSize,BlockSize+1> MB; + typedef Dune::FieldVector<matvec_t,BN> LVB; + typedef Dune::FieldVector<matvec_t,BM> VB; + typedef Dune::FieldMatrix<matvec_t,BN,BM> MB; typedef Dune::BlockVector<LVB> LeftVector; typedef Dune::BlockVector<VB> Vector; typedef Dune::BCRSMatrix<MB> Matrix; @@ -476,20 +172,24 @@ void test_matrix() // a += M * b _M.umv(b,a); +#ifndef NOPRINT printmatrix (std::cout, _M, "Matrix", "r"); printvector (std::cout, a, "Vector", "r"); +#endif // a = M * b +#if 0 a = _M*b; +#endif +#ifndef NOPRINT printvector (std::cout, a, "Vector", "r"); - - int N = 4; - int M = 5; +#endif Matrix A(N,M,Matrix::row_wise); - Matrix::CreateIterator i=A.createbegin(); - Matrix::CreateIterator end=A.createend(); + typename Matrix::CreateIterator i=A.createbegin(); + typename Matrix::CreateIterator end=A.createend(); + std::cout << "Building matrix structure\n"; // build up the matrix structure int c=0; for (; i!=end; ++i) @@ -500,27 +200,31 @@ void test_matrix() i.insert(M-1); c++; } - A = 0.0; + std::cout << "...done\n"; +#ifndef NOPRINT std::cout << "Matrix coldim=" << A.coldim() << std::endl; std::cout << "Matrix rowdim=" << A.rowdim() << std::endl; std::cout << "Matrix N=" << A.M() << std::endl; std::cout << "Matrix M=" << A.N() << std::endl; - Matrix::Iterator rit=A.begin(); - Matrix::Iterator rend=A.end(); + std::cout << "Assembling matrix\n"; + typename Matrix::Iterator rit=A.begin(); + typename Matrix::Iterator rend=A.end(); for (; rit!=rend; ++rit) { - Matrix::ColIterator cit=rit->begin(); - Matrix::ColIterator cend=rit->end(); + typename Matrix::ColIterator cit=rit->begin(); + typename Matrix::ColIterator cend=rit->end(); for (; cit!=cend; ++cit) { // *rit = rit.index(); *cit = 10*cit.index()+rit.index(); } } + std::cout << "...done\n"; printmatrix (std::cout, A, "Matrix", "r"); +#endif LeftVector v(N); LeftVector v2(N); @@ -533,24 +237,28 @@ void test_matrix() for (; fit!=fend; ++fit) *fit=c++; - std::cout << A.M() << " " << x.N() << " " << v.N() << std::endl; - + Dune::Timer stopwatch; + stopwatch.reset(); A.umv(x,v); + std::cout << "Time umv: " << stopwatch.elapsed() << std::endl; using namespace Dune; +#ifndef NOPRINT printvector (std::cout, x, "Vector X", "r"); printvector (std::cout, v, "Vector", "r"); - v=1; - MV<Matrix,Vector> eximp (A,x); - Dune::ExprTmpl::Expression< MV<Matrix,Vector> > ex ( eximp ); - v = ex; - printvector (std::cout, v, "Vector", "r"); - v2 = A * x; +#endif + v2 = 0; + stopwatch.reset(); + v2 += A * x; + std::cout << "Time v2+=A*x: " << stopwatch.elapsed() << std::endl; +#ifndef NOPRINT printvector (std::cout, v2, "Vector2", "r"); -#if 0 +#endif + +#ifndef NOPRINT int rowIndex[]={1}; - FlatColIterator<Matrix,Vector> it(A[2].begin(),rowIndex); + FlatColIterator<const Matrix> it(A[2].begin(),rowIndex); for (int i=0; i<5; i++) { std::cout << *it << " "; @@ -558,6 +266,7 @@ void test_matrix() } std::cout << std::endl; #endif + std::cout << std::endl; } int main() @@ -565,16 +274,23 @@ int main() // Dune::dvverb.attach(std::cout); try { - std::ofstream mylog("/dev/null"); - Dune::dvverb.attach(mylog); - test_fvector(); - test_blockvector(); - test_blockblockvector(); - test_matrix(); - exit(0); + // test_fvector(); + // test_blockvector(); + // test_blockblockvector(); + test_matrix<2,3,3,4>(); +#ifdef NOPRINT + test_matrix<3,6,400000,500000>(); + test_matrix<6,3,400000,500000>(); + test_matrix<30,60,4000,5000>(); + test_matrix<150,150,500,4000>(); + test_matrix<150,150,1000,2000>(); +#endif + // test_matrix<150,150,2000,1000>(); // fails in fmeta_something + // test_matrix<150,150,4000,500>(); // fails in fmeta_something } catch (Dune::Exception & e) { std::cout << e << std::endl; } + exit(0); } diff --git a/common/test/timing.cc b/common/test/timing.cc new file mode 100644 index 000000000..f9c07acf7 --- /dev/null +++ b/common/test/timing.cc @@ -0,0 +1,107 @@ +// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- +// vi: set et ts=4 sw=2 sts=2: +#include <iostream> +#include <fstream> +#include <dune/common/fvector.hh> +#include <dune/common/timer.hh> +#include <dune/istl/bvector.hh> +#include <dune/istl/io.hh> +#include <dune/common/iteratorfacades.hh> + +#ifdef DUNE_EXPRESSIONTEMPLATES +Indent INDENT; +#endif + +template<int bs, int sz> +void timing_vector() +{ + std::cout << "timing_vector<" << bs << ", " << sz << ">\n"; + typedef Dune::FieldVector<double,bs> VB; + typedef Dune::BlockVector<VB> BV; + typedef Dune::BlockVector<BV> BBV; + BV bv1(sz), bv2(sz); + bv1 = 1; + bv2 = 0; + bv2[1][0]=1; + bv2[1][1]=2; + + BBV bbv(2); + bbv[0].resize(bv1.N()); + bbv[1].resize(bv2.N()); + + Dune::Timer stopwatch; + stopwatch.reset(); + for (int i=0; i<100; i++) bbv *= 2; + std::cout << "Time [bbv*=2] " << stopwatch.elapsed() << std::endl; +} + +//template<int BlockSize, int N, int M> +template<int BN, int BM, int N, int M> +void timing_matrix() +{ + std::cout << "timing_matrix<" << BN << ", " << BM << ", " + << N << ", " << M << ">\n"; + + typedef double matvec_t; + typedef Dune::FieldVector<matvec_t,BN> LVB; + typedef Dune::FieldVector<matvec_t,BM> VB; + typedef Dune::FieldMatrix<matvec_t,BN,BM> MB; + typedef Dune::BlockVector<LVB> LeftVector; + typedef Dune::BlockVector<VB> Vector; + typedef Dune::BCRSMatrix<MB> Matrix; + + Matrix A(N,M,Matrix::row_wise); + typename Matrix::CreateIterator i=A.createbegin(); + typename Matrix::CreateIterator end=A.createend(); + std::cout << "Building matrix structure\n"; + // build up the matrix structure + int c=0; + for (; i!=end; ++i) + { + // insert a non zero entry for myself + i.insert(c); + // insert index M-1 + i.insert(M-1); + c++; + } + std::cout << "...done\n"; + + LeftVector v(N); + v = 0; + Vector x(M); + x = 1; + + Dune::Timer stopwatch; + stopwatch.reset(); +#ifdef DUNE_EXPRESSIONTEMPLATES + v += A * x; +#else + A.umv(x,v); +#endif + std::cout << "Time [v+=A*x] " << stopwatch.elapsed() << std::endl; + + std::cout << std::endl; +} + +int main () +{ +#ifdef DUNE_EXPRESSIONTEMPLATES + std::cout << "Expression Templates\n"; +#else + std::cout << "Old Version\n"; +#endif + + // timing_vector<1,1000000>(); + // timing_vector<10,100000>(); + // timing_vector<100,10000>(); + + // timing_matrix<150,150,500,4000>(); + // timing_matrix<150,150,1000,2000>(); + timing_matrix<1,18,400000,500000>(); + // timing_matrix<6,3,400000,500000>(); + // timing_matrix<3,6,400000,500000>(); + // timing_matrix<18,1,400000,500000>(); + // timing_matrix<50,50,9000,10000>(); + + std::cout << std::endl; +} diff --git a/istl/bcrsmatrix.hh b/istl/bcrsmatrix.hh index c88efcf54..22e569dc7 100644 --- a/istl/bcrsmatrix.hh +++ b/istl/bcrsmatrix.hh @@ -52,8 +52,13 @@ namespace Dune { Setting the compile time switch DUNE_ISTL_WITH_CHECKING enables error checking. */ +#ifdef DUNE_EXPRESSIONTEMPLATES + template<class B, class A> + class BCRSMatrix : public ExprTmpl::Matrix< BCRSMatrix<B,A> > +#else template<class B, class A=ISTLAllocator> class BCRSMatrix +#endif { public: @@ -1282,6 +1287,25 @@ namespace Dune { }; +#ifdef DUNE_EXPRESSIONTEMPLATES + template <class B, class A> + struct FieldType< BCRSMatrix<B,A> > + { + typedef typename FieldType<B>::type type; + }; + + template <class B, class A> + struct BlockType< BCRSMatrix<B,A> > + { + typedef B type; + }; + template <class B, class A> + struct RowType< BCRSMatrix<B,A> > + { + typedef CompressedBlockVectorWindow<B,A> type; + }; +#endif + /** @} end documentation */ } // end namespace diff --git a/istl/bvector.hh b/istl/bvector.hh index 07da9b6a8..9b6eec2be 100644 --- a/istl/bvector.hh +++ b/istl/bvector.hh @@ -222,10 +222,13 @@ namespace Dune { Setting the compile time switch DUNE_ISTL_WITH_CHECKING enables error checking. */ +#ifdef DUNE_EXPRESSIONTEMPLATES + template<class B, class A> + class BlockVector : public block_vector_unmanaged<B,A> , + public Dune::ExprTmpl::Vector< Dune::BlockVector<B,A> > +#else template<class B, class A=ISTLAllocator> class BlockVector : public block_vector_unmanaged<B,A> -#ifdef DUNE_EXPRESSIONTEMPLATES - , public Dune::ExprTmpl::Vector< Dune::BlockVector<B,A> > #endif { public: -- GitLab