Newer
Older
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
#ifndef DUNE_FVECTOR_HH
#define DUNE_FVECTOR_HH
#include <cmath>
#include <cstddef>
Steffen Müthing
committed
#include <utility>
#include <initializer_list>
#include <algorithm>
#include <dune/common/std/constexpr.hh>
#include "typetraits.hh"
#include "array.hh"
#include "ftraits.hh"
#include "densevector.hh"
#include "unused.hh"
/** @addtogroup DenseMatVec
@{
* \brief Implements a vector constructed from a given type
representing a field and a compile-time given size.
*/
template< class K, int SIZE > class FieldVector;
template< class K, int SIZE >
struct DenseMatVecTraits< FieldVector<K,SIZE> >
{
typedef FieldVector<K,SIZE> derived_type;
typedef Dune::array<K,SIZE> container_type;
typedef K value_type;
typedef typename container_type::size_type size_type;
};
template< class K, int SIZE >
struct FieldTraits< FieldVector<K,SIZE> >
{
typedef typename FieldTraits<K>::field_type field_type;
typedef typename FieldTraits<K>::real_type real_type;
};
/**
* @brief TMP to check the size of a DenseVectors statically, if possible.
*
* If the implementation type of C is a FieldVector, we statically check
* whether its dimension is SIZE.
* @tparam C The implementation of the other DenseVector
* @tparam SIZE The size we need assume.
*/
template<typename C, int SIZE>
struct IsFieldVectorSizeCorrect
{
enum {
/**
*@param True if C is not of type FieldVector or its dimension
* is not equal SIZE.
*/
value = true
};
};
template<typename T, int SIZE>
struct IsFieldVectorSizeCorrect<FieldVector<T,SIZE>,SIZE>
{
enum {value = true};
};
template<typename T, int SIZE, int SIZE1>
struct IsFieldVectorSizeCorrect<FieldVector<T,SIZE1>,SIZE>
{
enum {value = false};
};
/** \brief vector space out of a tensor product of fields.
* \tparam K the field type (use float, double, complex, etc)
* \tparam SIZE number of components.
template< class K, int SIZE >
class FieldVector :
public DenseVector< FieldVector<K,SIZE> >
Dune::array<K,SIZE> _data;
typedef DenseVector< FieldVector<K,SIZE> > Base;
//! The size of this vector.
dimension = SIZE
typedef typename Base::size_type size_type;
typedef typename Base::value_type value_type;
Steffen Müthing
committed
//! Constructor making default-initialized vector
FieldVector()
: _data{}
{}
//! Constructor making vector with identical coordinates
explicit FieldVector (const K& t)
{
Andreas Dedner
committed
fill(t);
//! Constructor making vector with identical coordinates
FieldVector (const FieldVector & x) : _data(x._data)
{}
FieldVector (std::initializer_list<K> const &l)
{
assert(l.size() == dimension);// Actually, this is not needed any more!
std::copy_n(l.begin(), std::min(static_cast<std::size_t>(dimension),
l.size()),
_data.begin());
}
* \brief Copy constructor from a second vector of possibly different type
* If the DenseVector type of the this constructor's argument
* is implemented by a FieldVector, it is statically checked
* if it has the correct size. If this is not the case
* the constructor is removed from the overload set using SFINAE.
*
* \param[in] x A DenseVector with correct size.
* \param[in] dummy A void* dummy argument needed by SFINAE.
*/
template<class C>
FieldVector (const DenseVector<C> & x, typename Dune::enable_if<IsFieldVectorSizeCorrect<C,SIZE>::value>::type* dummy=0 )
{
DUNE_UNUSED_PARAMETER(dummy);
// do a run-time size check, for the case that x is not a FieldVector
assert(x.size() == SIZE); // Actually this is not needed any more!
std::copy_n(x.begin(), std::min(static_cast<std::size_t>(SIZE),x.size()), _data.begin());
}
//! Constructor making vector with identical coordinates
template<class K1, int SIZE1>
explicit FieldVector (const FieldVector<K1,SIZE1> & x)
{
static_assert(SIZE1 == SIZE, "FieldVector in constructor has wrong size");
for (size_type i = 0; i<SIZE; i++)
_data[i] = x[i];
}
using Base::operator=;
DUNE_CONSTEXPR size_type size () const { return vec_size(); }
// make this thing a vector
DUNE_CONSTEXPR size_type vec_size () const { return SIZE; }
K & vec_access(size_type i) { return _data[i]; }
const K & vec_access(size_type i) const { return _data[i]; }
Andreas Dedner
committed
private:
void fill(const K& t)
{
for (int i=0; i<SIZE; i++) _data[i]=t;
}
/** \brief Read a FieldVector from an input stream
* \relates FieldVector
*
* \note This operator is STL compliant, i.e., the content of v is only
* changed if the read operation is successful.
*
* \param[in] in std :: istream to read from
* \param[out] v FieldVector to be read
*
* \returns the input stream (in)
*/
inline std::istream &operator>> ( std::istream &in,
FieldVector<K, SIZE> &v )
FieldVector<K, SIZE> w;
for( typename FieldVector<K, SIZE>::size_type i = 0; i < SIZE; ++i )
if(in)
template< class K >
struct DenseMatVecTraits< FieldVector<K,1> >
{
typedef FieldVector<K,1> derived_type;
typedef K container_type;
typedef K value_type;
typedef size_t size_type;
};
/** \brief Vectors containing only one component
Christian Engwer
committed
*/
template<class K>
class FieldVector<K, 1> :
public DenseVector< FieldVector<K,1> >
K _data;
typedef DenseVector< FieldVector<K,1> > Base;
public:
//! export size
enum {
//! The size of this vector.
dimension = 1
};
typedef typename Base::size_type size_type;
//===== construction
/** \brief Default constructor */
Steffen Müthing
committed
FieldVector ()
: _data()
{}
/** \brief Constructor with a given scalar */
Christian Engwer
committed
template<typename T,
typename EnableIf = typename std::enable_if<
std::is_convertible<T, K>::value &&
! std::is_same<K, DenseVector<typename FieldTraits<T>::field_type>
>::value
>::type
>
FieldVector (const T& k) : _data(k) {}
//! Constructor making vector with identical coordinates
template<class C>
FieldVector (const DenseVector<C> & x)
{
static_assert(((bool)IsFieldVectorSizeCorrect<C,1>::value), "FieldVectors do not match in dimension!");
assert(x.size() == 1);
_data = x[0];
}
//! copy constructor
FieldVector ( const FieldVector &other )
: _data( other._data )
{}
//! Assignment operator for scalar
Christian Engwer
committed
template<typename T,
typename EnableIf = typename std::enable_if<
std::is_convertible<T, K>::value &&
! std::is_same<K, DenseVector<typename FieldTraits<T>::field_type>
>::value
>::type
>
inline FieldVector& operator= (const T& k)
{
_data = k;
return *this;
}
DUNE_CONSTEXPR size_type size () const { return vec_size(); }
//===== forward methods to container
DUNE_CONSTEXPR size_type vec_size () const { return 1; }
K & vec_access(size_type i)
{
assert(i == 0);
return _data;
}
const K & vec_access(size_type i) const
{
assert(i == 0);
return _data;
}
//===== conversion operator
/** \brief Conversion operator */
Oliver Sander
committed
operator K& () { return _data; }
/** \brief Const conversion operator */
Oliver Sander
committed
operator const K& () const { return _data; }
/* ----- FV / FV ----- */
/* not necessary as these operations are already covered via the cast operator */
/* ----- FV / scalar ----- */
//! Binary addition, when using FieldVector<K,1> like K
template<class K>
inline FieldVector<K,1> operator+ (const FieldVector<K,1>& a, const K b)
{
return a[0]+b;
}
//! Binary subtraction, when using FieldVector<K,1> like K
template<class K>
inline FieldVector<K,1> operator- (const FieldVector<K,1>& a, const K b)
{
return a[0]-b;
}
//! Binary multiplication, when using FieldVector<K,1> like K
inline FieldVector<K,1> operator* (const FieldVector<K,1>& a, const K b)
return a[0]*b;
//! Binary division, when using FieldVector<K,1> like K
inline FieldVector<K,1> operator/ (const FieldVector<K,1>& a, const K b)
return a[0]/b;
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
inline bool operator> (const FieldVector<K,1>& a, const K b)
{
return a[0]>b;
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
inline bool operator>= (const FieldVector<K,1>& a, const K b)
{
return a[0]>=b;
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
inline bool operator< (const FieldVector<K,1>& a, const K b)
{
return a[0]<b;
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
inline bool operator<= (const FieldVector<K,1>& a, const K b)
{
return a[0]<=b;
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
inline bool operator== (const FieldVector<K,1>& a, const K b)
{
return a[0]==b;
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
inline bool operator!= (const FieldVector<K,1>& a, const K b)
{
return a[0]!=b;
}
/* ----- scalar / FV ------ */
//! Binary addition, when using FieldVector<K,1> like K
template<class K>
inline FieldVector<K,1> operator+ (const K a, const FieldVector<K,1>& b)
{
return a+b[0];
}
//! Binary subtraction, when using FieldVector<K,1> like K
template<class K>
inline FieldVector<K,1> operator- (const K a, const FieldVector<K,1>& b)
{
return a-b[0];
//! Binary multiplication, when using FieldVector<K,1> like K
template<class K>
inline FieldVector<K,1> operator* (const K a, const FieldVector<K,1>& b)
{
return a*b[0];
}
//! Binary division, when using FieldVector<K,1> like K
template<class K>
inline FieldVector<K,1> operator/ (const K a, const FieldVector<K,1>& b)
{
return a/b[0];
}
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
inline bool operator> (const K a, const FieldVector<K,1>& b)
{
return a>b[0];
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
inline bool operator>= (const K a, const FieldVector<K,1>& b)
{
return a>=b[0];
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
inline bool operator< (const K a, const FieldVector<K,1>& b)
{
return a<b[0];
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
inline bool operator<= (const K a, const FieldVector<K,1>& b)
{
return a<=b[0];
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
inline bool operator== (const K a, const FieldVector<K,1>& b)
{
return a==b[0];
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
inline bool operator!= (const K a, const FieldVector<K,1>& b)
{
return a!=b[0];
}
/** @} end documentation */
} // end namespace
#endif