Forked from
Core Modules / dune-common
6949 commits behind the upstream repository.
-
Oliver Sander authored
[[Imported from SVN: r5222]]
Oliver Sander authored[[Imported from SVN: r5222]]
exprtmpl.hh 29.12 KiB
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#if ! defined DUNE_EXPRTMPL_HH && DUNE_EXPRESSIONTEMPLATES
#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>
#include <cmath>
#include <complex>
#include "iteratorfacades.hh"
#include "static_assert.hh"
#include "stdstreams.hh"
struct Indent
{
int i;
Indent() {
i = 0;
}
void operator ++ ()
{
#ifdef DUNE_VVERBOSE
i += 3;
#endif
};
void operator -- ()
{
#ifdef DUNE_VVERBOSE
i -= 3;
#endif
};
};
extern Indent INDENT;
inline std::ostream & operator << (std::ostream & s, const Indent & i)
{
#ifdef DUNE_VVERBOSE
for (int n = 0; n < i.i; n++) s << " ";
#endif
return s;
}
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
*/
template<class T>
struct BlockType
{};
template<class T>
struct FieldType
{};
// FieldType specializations for basic data types
template<>
struct FieldType<double>
{
typedef double type;
};
template<>
struct FieldType<float>
{
typedef float type;
};
template<>
struct FieldType<int>
{
typedef int type;
};
// FieldType specialization for FieldVector
template <class K, int N>
struct FieldType< FieldVector<K,N> >
{
typedef K type;
};
// BlockType specialization for FieldVector
template <class K, int N>
struct BlockType< FieldVector<K,N> >
{
typedef K type;
};
// FieldType specialization for const T
template<class T>
struct FieldType<const T>
{
typedef const typename FieldType<T>::type type;
};
// BlockType specialization for const T
template<class T>
struct BlockType<const T>
{
typedef const typename BlockType<T>::type type;
};
namespace ExprTmpl {
/* Important Classes */
template <class V> class ConstRef;
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
*/
template<class T>
struct BlockExpression
{};
/**
Type Trait for Implementation of an Expression
*/
template<class T>
struct ExpressionImp
{};
template <class V>
struct ExpressionImp< ExprTmpl::ConstRef<V> >
{
typedef ExprTmpl::ConstRef<V> type;
};
// TypeTraits
template <>
struct ExpressionImp<double>
{
typedef double type;
};
template <>
struct ExpressionImp<float>
{
typedef float type;
};
template <>
struct ExpressionImp<int>
{
typedef int type;
};
template <class Ex>
struct ExpressionImp< Expression<Ex> >
{
typedef Ex type;
};
/** Identify End of Expression Recursion */
template <class V>
struct isEndOfExpressionRecusion
{
enum { value=false };
};
template <>
struct isEndOfExpressionRecusion<double>
{
enum { value=true };
};
template <class K>
struct isEndOfExpressionRecusion< FieldVector<K,1> >
{
enum { value=true };
};
template <class K>
struct isEndOfExpressionRecusion< std::complex<K> >
{
enum { value=true };
};
template <>
struct isEndOfExpressionRecusion<int>
{
enum { value=true };
};
template <>
struct isEndOfExpressionRecusion<float>
{
enum { value=true };
};
/** Nested Expression in a ConstRef<V> */
template <class V>
struct BlockExpression< ConstRef<V> >
{
typedef ExprTmpl::Expression<
ExprTmpl::ConstRef<typename BlockType<V>::type> > type;
};
/** No nested Expression in ConstRef<FieldVector> */
template<class K, int N>
struct BlockExpression< ConstRef< FieldVector<K,N> > >
{
typedef K type;
};
/**
Wrapper for an expression template
*/
template <class Ex>
class Expression
{
public:
Expression(const Ex & x) : ex(x) {}
typedef typename FieldType<Ex>::type field_type;
typedef typename BlockExpression<Ex>::type BlockExpr;
BlockExpr operator[] ( int i ) const {
return ex[i];
}
size_t N() const { return ex.N(); }
double one_norm() const { return eval_one_norm(*this); }
double one_norm_real() const { return eval_one_norm_real(*this); }
double two_norm() const { return sqrt(eval_two_norm2(*this)); }
double two_norm2() const { return eval_two_norm2(*this); }
double infinity_norm() const { return eval_infinity_norm(*this); }
double infinity_norm_real() const { return eval_infinity_norm_real(*this); }
private:
Ex ex;
};
/**
Vector Base Class for Expression Templates
*/
template <class I>
class Vector {
public:
explicit Vector() {}
typedef typename BlockType<I>::type block_type;
typedef typename FieldType<I>::type field_type;
//! dimension of the vector space
size_t N() const {
return asImp().N();
}
double one_norm() const { return eval_one_norm(*this); }
double one_norm_real() const { return eval_one_norm_real(*this); }
double two_norm() const { return sqrt(eval_two_norm2(*this)); }
double two_norm2() const { return eval_two_norm2(*this); }
double infinity_norm() const { return eval_infinity_norm(*this); }
double infinity_norm_real() const { return eval_infinity_norm_real(*this); }
block_type & operator[] (int i) {
return asImp()[i];
}
const block_type & operator[] (int i) const {
return asImp()[i];
}
//! begin for FlatIterator
FlatIterator<I> fbegin() { return FlatIterator<I>(asImp().begin()); }
//! end for FlatIterator
FlatIterator<I> fend() { return FlatIterator<I>(asImp().end()); }
//! begin for ConstFlatIterator
FlatIterator<const I> fbegin() const {
return FlatIterator<const I>(asImp().begin());
}
//! end for ConstFlatIterator
FlatIterator<const I> fend() const {
return FlatIterator<const I>(asImp().end());
}
//! assign Vector from Expression
template <class E> I& assignFrom(Expression<E>& x) {
#warning should there be a resize?
#ifdef DUNE_ISTL_WITH_CHECKING
assert(N() == x.N());
#endif
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "Assign Vector from Expression\n";
#endif
++INDENT;
for (int i=0; i<N(); ++i) { asImp()[i] = x[i]; }
--INDENT;
return asImp();
}
//! assign Vector from Vector
template <class V> I& assignFrom(const Vector<V>& v) {
#ifdef DUNE_ISTL_WITH_CHECKING
assert(N() == v.N());
#endif
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "Assign Vector from Vector\n";
#endif
++INDENT;
for (int i=0; i<N(); ++i) { asImp()[i] = v[i]; }
--INDENT;
return asImp();
}
/*
I& assignFrom(const Vector<block_type> & x) {
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "Assign Vector block_type\n";
#endif
++INDENT;
for (int i=0; i < asImp().N(); i++) asImp()[i] = x;
--INDENT;
return asImp();
}
*/
I& assignFrom(field_type x) {
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "Assign Vector from field_type\n";
#endif
++INDENT;
for (size_t i=0; i<N(); ++i) { asImp()[i] = x; }
--INDENT;
return asImp();
}
template <class E> Vector<I>& operator+=(const Expression<E>& x) {
for (size_t i=0; i < asImp().N(); i++) asImp()[i] += x[i];
return asImp();
}
template <class V> Vector<I>& operator+=(const Vector<V>& x) {
for (size_t i=0; i < asImp().N(); i++) asImp()[i] += x[i];
return asImp();
}
template <class E> Vector<I>& operator-=(const Expression<E>& x) {
for (size_t i=0; i < asImp().N(); i++) asImp()[i] -= x[i];
return asImp();
}
template <class V> Vector<I>& operator-=(const Vector<V>& x) {
for (size_t i=0; i < asImp().N(); i++) asImp()[i] -= x[i];
return asImp();
}
Vector<I>& operator+=(field_type x) {
for (size_t i=0; i < asImp().N(); i++) asImp()[i] += x;
return asImp();
}
Vector<I>& operator-=(field_type x) {
for (size_t i=0; i < asImp().N(); i++) asImp()[i] -= x;
return asImp();
}
Vector<I>& operator*=(field_type x) {
for (size_t i=0; i < asImp().N(); i++) asImp()[i] *= x;
return asImp();
}
Vector<I>& operator/=(field_type x) {
for (size_t i=0; i < asImp().N(); i++) asImp()[i] /= x;
return asImp();
}
private:
I & asImp() { return static_cast<I&>(*this); }
const I & asImp() const { return static_cast<const I&>(*this); }
};
template <class V>
class ConstRef
{
public:
typedef typename FieldType<V>::type field_type;
typedef typename BlockType<V>::type block_type;
typedef typename BlockExpression< ConstRef<V> >::type BlockExpr;
typedef typename ExpressionImp<BlockExpr>::type BlockExprImp;
ConstRef (const Vector<V> & _v) : v(_v) {}
BlockExpr operator[] (int i) const {
#ifdef DUNE_VVERBOSE
Dune::dvverb << INDENT << "ConstRef->dereference " << v[i] << std::endl;
#endif
return BlockExprImp(v[i]);
}
size_t N() const { return v.N(); };
double one_norm() const { return eval_one_norm(*this); }
double one_norm_real() const { return eval_one_norm_real(*this); }
double two_norm() const { return sqrt(eval_two_norm2(*this)); }
double two_norm2() const { return eval_two_norm2(*this); }
double infinity_norm() const { return eval_infinity_norm(*this); }
double infinity_norm_real() const { return eval_infinity_norm_real(*this); }
private:
const Vector<V> & v;
};
} // namespace ExprTmpl
template <class A>
struct FieldType< ExprTmpl::Expression<A> >
{
typedef typename FieldType<A>::type type;
};
template <class V>
struct FieldType< ExprTmpl::ConstRef<V> >
{
typedef typename FieldType<V>::type type;
};
template <class I>
struct FieldType< ExprTmpl::Vector<I> >
{
typedef typename FieldType<I>::type type;
};
// ----
template <class A>
struct BlockType< ExprTmpl::Expression<A> >
{
typedef typename BlockType<A>::type type;
};
template <class V>
struct BlockType< ExprTmpl::ConstRef<V> >
{
typedef typename BlockType<V>::type type;
};
template <class I>
struct BlockType< ExprTmpl::Vector<I> >
{
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
size_t 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);
}
size_t 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);
}
size_t 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;
}
size_t N() const { return 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;
}
size_t N() const { return 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
/* Scalar-Expression Operator */
#define OP *
#define ExpressionOpScalar ExpressionMulScalar
#define ScalarOpExpression ScalarMulExpression
#include "exprtmpl/scalar.inc"
#define OP /
#define ExpressionOpScalar ExpressionDivScalar
#include "exprtmpl/scalar.inc"
#define OP +
#define ExpressionOpScalar ExpressionAddScalar
#define ScalarOpExpression ScalarAdExpression
#include "exprtmpl/scalar.inc"
#define OP -
#define ExpressionOpScalar ExpressionMinScalar
#define ScalarOpExpression ScalarMinExpression
#include "exprtmpl/scalar.inc"
/* Expression-Expression Operator */
#define OP +
#define ExpressionOpExpression ExpressionAddExpression
#include "exprtmpl/exprexpr.inc"
#define OP -
#define ExpressionOpExpression ExpressionMinExpression
#include "exprtmpl/exprexpr.inc"
/* one norm (sum over absolute values of entries) */
#define NORM eval_one_norm
#define NORM_CODE \
{ \
typename FieldType<A>::type val=0; \
Dune::dvverb << INDENT << "Infinity Norm of Expression\n"; \
++INDENT; \
for (size_t i=0; i<a.N(); ++i) { val += eval_one_norm(a[i]); } \
--INDENT; \
return val; \
}
#define VAL_CODE { return std::abs(a); }
#include "exprtmpl/norm.inc"
template<class K>
inline K eval_one_norm (const std::complex<K>& c)
{
sqrt(c.real()*c.real() + c.imag()*c.imag());
}
template <class A>
typename FieldType<A>::type
one_norm (const A & a)
{
return eval_one_norm(a);
}
/* simplified one norm (uses Manhattan norm for complex values) */
#define NORM eval_one_norm_real
#define NORM_CODE \
{ \
typename FieldType<A>::type val=0; \
Dune::dvverb << INDENT << "Infinity Norm of Expression\n"; \
++INDENT; \
for (size_t i=0; i<a.N(); ++i) { val += eval_one_norm_real(a[i]); } \
--INDENT; \
return val; \
}
#define VAL_CODE { return std::abs(a); }
#include "exprtmpl/norm.inc"
template<class K>
inline K eval_one_norm_real (const std::complex<K>& c)
{
return eval_one_norm_real(c.real()) + eval_one_norm_real(c.imag());
}
template <class A>
typename FieldType<A>::type
one_norm_real (const A & a)
{
return eval_one_norm_real(a);
}
/* two norm sqrt(sum over squared values of entries) */
template <class A>
typename FieldType<A>::type
two_norm (const A & a)
{
return sqrt(eval_two_norm2(a));
}
/* sqare of two norm (sum over squared values of entries), need for block recursion */
#define NORM eval_two_norm2
#define NORM_CODE \
{ \
typename FieldType<A>::type val=0; \
Dune::dvverb << INDENT << "Infinity Norm of Expression\n"; \
++INDENT; \
for (size_t i=0; i<a.N(); ++i) { val += eval_two_norm2(a[i]); } \
--INDENT; \
return val; \
}
#define VAL_CODE { return a*a; }
#include "exprtmpl/norm.inc"
template<class K>
inline K eval_two_norm2 (const std::complex<K>& c)
{
return c.real()*c.real() + c.imag()*c.imag();
}
template <class A>
typename FieldType<A>::type
two_norm2 (const A & a)
{
return eval_two_norm2(a);
}
/* infinity norm (maximum of absolute values of entries) */
#define NORM eval_infinity_norm
#define NORM_CODE { \
typename FieldType<A>::type val=0; \
Dune::dvverb << INDENT << "Infinity Norm of Expression\n"; \
++INDENT; \
for (size_t i=0; i<a.N(); ++i) { val = std::max(val,eval_infinity_norm(a[i])); } \
--INDENT; \
return val; \
}
#define VAL_CODE { return a; }
#include "exprtmpl/norm.inc"
template <class A>
typename FieldType<A>::type
infinity_norm (const A & a)
{
return eval_infinity_norm(a);
}
/* simplified infinity norm (uses Manhattan norm for complex values) */
#define NORM eval_infinity_norm_real
#define NORM_CODE { \
typename FieldType<A>::type val=0; \
Dune::dvverb << INDENT << "Infinity Norm of Expression\n"; \
++INDENT; \
for (size_t i=0; i<a.N(); ++i) { val = std::max(val,eval_infinity_norm(a[i])); } \
--INDENT; \
return val; \
}
#define VAL_CODE { return std::abs(a); }
#include "exprtmpl/norm.inc"
template<class K>
inline K eval_infinity_norm_real (const std::complex<K>& c)
{
return eval_one_norm_real(c.real()) + eval_one_norm_real(c.imag());
}
template <class A>
typename FieldType<A>::type
infinity_norm_real (const A & a)
{
return eval_infinity_norm(a);
}
/* vector * vector */
namespace ExprTmpl {
// Vector * Vector
template <class A>
typename FieldType<A>::type
operator * (const Vector<A> & a, const Vector<A> & b)
{
assert(a.N() == b.N());
typename FieldType<A>::type x = 0;
for (size_t i=0; i<a.N(); i++)
x = a[i] * b[i];
return x;
}
// Expression * Vector
template <class A, class B>
typename FieldType<A>::type
operator * (const Vector<A> & a, const Expression<B> & b)
{
dune_static_assert((is_same<FieldType<A>,FieldType<B> >::value),
"Field types of both operands must match!");
assert(a.N() == b.N());
typename FieldType<A>::type x = 0;
for (size_t i=0; i<a.N(); i++)
x = a[i] * b[i];
return x;
}
// Vector * Expression
template <class A, class B>
typename FieldType<A>::type
operator * (const Expression<A> & a, const Vector<B> & b)
{
dune_static_assert((is_same<FieldType<A>,FieldType<B> >::value),
"Field types of both operands must match!");
assert(a.N() == b.N());
typename FieldType<A>::type x = 0;
for (size_t i=0; i<a.N(); i++)
x = a[i] * b[i];
return x;
}
} // namespace ExprTmpl
} // namespace Dune
#endif // DUNE_EXPRTMPL_HH