Skip to content
Snippets Groups Projects

Draft: Remove the FieldVector<K,1> specialization

Open Simon Praetorius requested to merge issue/fieldvector-1-constructors-2 into master
Compare and
1 file
+ 213
391
Compare changes
  • Side-by-side
  • Inline
+ 213
391
@@ -8,6 +8,7 @@
#include <algorithm>
#include <array>
#include <cmath>
#include <concepts>
#include <cstdlib>
#include <cstring>
#include <type_traits>
@@ -16,11 +17,15 @@
#include <dune/common/boundschecking.hh>
#include <dune/common/densevector.hh>
#include <dune/common/filledarray.hh>
#include <dune/common/ftraits.hh>
#include <dune/common/math.hh>
#include <dune/common/promotiontraits.hh>
#include <dune/common/typetraits.hh>
#include <dune/common/typeutilities.hh>
#include <dune/common/concepts/number.hh>
#include <dune/common/std/algorithm.hh>
#include <dune/common/std/compare.hh>
namespace Dune {
@@ -90,119 +95,149 @@ namespace Dune {
class FieldVector :
public DenseVector< FieldVector<K,SIZE> >
{
using Base = DenseVector< FieldVector<K,SIZE> >;
//! The container storage
std::array<K,SIZE> _data;
typedef DenseVector< FieldVector<K,SIZE> > Base;
public:
//! The size of this vector.
constexpr static int dimension = SIZE;
static constexpr int dimension = SIZE;
//! The type used for the index access and size operation
using size_type = typename Base::size_type;
typedef typename Base::size_type size_type;
typedef typename Base::value_type value_type;
//! The type of the elements stored in the vector
using value_type = typename Base::value_type;
/** \brief The type used for references to the vector entry */
typedef value_type& reference;
//! The type used for references to the vector entries
using reference = value_type&;
/** \brief The type used for const references to the vector entry */
typedef const value_type& const_reference;
//! The type used for const references to the vector entries
using const_reference = const value_type&;
public:
//! Default constructor, making value-initialized vector with all components set to zero
constexpr FieldVector () noexcept
constexpr FieldVector ()
noexcept(std::is_nothrow_default_constructible_v<K>)
: _data{}
{}
//! Constructor making vector with identical coordinates
explicit constexpr FieldVector (const K& k)
noexcept(std::is_nothrow_copy_assignable_v<K>)
{
std::fill(_data.begin(), _data.end(), k);
}
//! Constructor with a given value initializing all entries to this value
explicit(SIZE != 1) constexpr FieldVector (const value_type& value) noexcept
: _data{filledArray<SIZE>(value)}
{}
//! Constructor with a given scalar initializing all entries to this value
template<Concept::Number S>
requires (std::constructible_from<K,S>)
explicit(SIZE != 1) constexpr FieldVector (const S& scalar)
noexcept(std::is_nothrow_constructible_v<K,S>)
: _data{filledArray<SIZE,K>(K(scalar))}
{}
//! Construct from a std::initializer_list
//! Construct from a std::initializer_list of values
constexpr FieldVector (const std::initializer_list<K>& l)
: _data{}
{
assert(l.size() == dimension);
for (int i = 0; i < dimension; ++i)
assert(l.size() == size());
for (size_type i = 0; i < size(); ++i)
_data[i] = std::data(l)[i];
}
//! Constructor from another dense vector if the elements are assignable to K
template<class T,
std::enable_if_t<IsFieldVectorSizeCorrect<T,dimension>::value, int> = 0,
decltype(std::declval<K&>() = std::declval<const T&>()[0], bool{}) = true>
FieldVector (const DenseVector<T>& x)
template<class V>
requires (IsFieldVectorSizeCorrect<V,SIZE>::value &&
std::is_assignable_v<K&, decltype(std::declval<const V&>()[0])>)
FieldVector (const DenseVector<V>& x)
{
assert(x.size() == dimension);
for (int i = 0; i < dimension; ++i)
assert(x.size() == size());
for (size_type i = 0; i < size(); ++i)
_data[i] = x[i];
}
//! Converting constructor from FieldVector with different element type
template<class T,
std::enable_if_t<std::is_assignable_v<K&, const T&>, int> = 0>
explicit constexpr FieldVector (const FieldVector<T, SIZE>& x)
noexcept(std::is_nothrow_assignable_v<K&, const T&>)
template<class OtherK>
requires (std::is_assignable_v<K&, const OtherK&>)
explicit constexpr FieldVector (const FieldVector<OtherK, SIZE>& x)
noexcept(std::is_nothrow_assignable_v<K&, const OtherK&>)
{
for (int i = 0; i < dimension; ++i)
for (size_type i = 0; i < size(); ++i)
_data[i] = x[i];
}
//! Converting constructor with FieldVector of different size (deleted)
template<class K1, int SIZE1,
std::enable_if_t<(SIZE1 != SIZE), int> = 0>
explicit FieldVector (const FieldVector<K1, SIZE1>&) = delete;
//! Copy constructor with default behavior
FieldVector (const FieldVector&) = default;
constexpr FieldVector (const FieldVector&) = default;
//! Assignment from another dense vector
template<class T,
std::enable_if_t<IsFieldVectorSizeCorrect<T,dimension>::value, int> = 0,
decltype(std::declval<K&>() = std::declval<const T&>()[0], bool{}) = true>
FieldVector& operator= (const DenseVector<T>& x)
template<class V>
requires (IsFieldVectorSizeCorrect<V,SIZE>::value &&
std::is_assignable_v<K&, decltype(std::declval<const V&>()[0])>)
FieldVector& operator= (const DenseVector<V>& x)
{
assert(x.size() == dimension);
for (int i = 0; i < dimension; ++i)
assert(x.size() == size());
for (size_type i = 0; i < size(); ++i)
_data[i] = x[i];
return *this;
}
//! Assignment operator from scalar
template<Concept::Number S>
requires std::constructible_from<K,S>
constexpr FieldVector& operator= (const S& scalar)
noexcept(std::is_nothrow_constructible_v<K,S>)
{
_data.fill(K(scalar));
return *this;
}
//! Converting assignment operator from FieldVector with different element type
template<class T,
std::enable_if_t<std::is_assignable_v<K&, const T&>, int> = 0>
FieldVector& operator= (const FieldVector<T, SIZE>& x)
noexcept(std::is_nothrow_assignable_v<K&, const T&>)
template<class OtherK>
requires (std::is_assignable_v<K&, const OtherK&>)
constexpr FieldVector& operator= (const FieldVector<OtherK, SIZE>& x)
noexcept(std::is_nothrow_assignable_v<K&, const OtherK&>)
{
for (int i = 0; i < dimension; ++i)
for (size_type i = 0; i < size(); ++i)
_data[i] = x[i];
return *this;
}
//! Converting assignment operator with FieldVector of different size (deleted)
template<class K1, int SIZE1,
std::enable_if_t<(SIZE1 != SIZE), int> = 0>
FieldVector& operator= (const FieldVector<K1, SIZE1>&) = delete;
//! Copy assignment operator with default behavior
constexpr FieldVector& operator= (const FieldVector&) = default;
using Base::operator=;
/// \name Capacity
/// @{
//! Obtain the number of elements stored in the vector
static constexpr size_type size () noexcept { return dimension; }
static constexpr size_type size () noexcept { return SIZE; }
//! Return a reference to the `i`th element
reference operator[] (size_type i)
/// @}
/// \name Element access
/// @{
/**
* \brief Return a reference to the `i`th element.
* \throw RangeError if index `i` is out of range `[0,SIZE)` (only checked if DUNE_CHECK_BOUNDS is defined).
*/
constexpr reference operator[] (size_type i)
{
DUNE_ASSERT_BOUNDS(i < dimension);
DUNE_ASSERT_BOUNDS(i < size());
return _data[i];
}
//! Return a (const) reference to the `i`th element
const_reference operator[] (size_type i) const
/**
* \brief Return a (const) reference to the `i`th element.
* \throw RangeError if index `i` is out of range `[0,SIZE)` (only checked if DUNE_CHECK_BOUNDS is defined).
*/
constexpr const_reference operator[] (size_type i) const
{
DUNE_ASSERT_BOUNDS(i < dimension);
DUNE_ASSERT_BOUNDS(i < size());
return _data[i];
}
@@ -218,383 +253,170 @@ namespace Dune {
return _data.data();
}
//! Vector space multiplication with scalar
template<class Scalar,
std::enable_if_t<IsNumber<Scalar>::value, int> = 0>
friend constexpr auto operator* (const FieldVector& vector, Scalar scalar)
//! Conversion operator
constexpr operator const_reference () const noexcept
requires(SIZE == 1)
{
using T = typename PromotionTraits<value_type,Scalar>::PromotedType;
FieldVector<T,SIZE> result;
for (size_type i = 0; i < vector.size(); ++i)
result[i] = vector[i] * scalar;
return result;
return _data[0];
}
//! Vector space multiplication with scalar
template<class Scalar,
std::enable_if_t<IsNumber<Scalar>::value, int> = 0>
friend constexpr auto operator* (Scalar scalar, const FieldVector& vector)
//! Conversion operator
constexpr operator reference () noexcept
requires(SIZE == 1)
{
using T = typename PromotionTraits<value_type,Scalar>::PromotedType;
FieldVector<T,SIZE> result;
for (size_type i = 0; i < vector.size(); ++i)
result[i] = scalar * vector[i];
return result;
return _data[0];
}
//! Vector space division by scalar
template<class Scalar,
std::enable_if_t<IsNumber<Scalar>::value, int> = 0>
friend constexpr auto operator/ (const FieldVector& vector, Scalar scalar)
{
using T = typename PromotionTraits<value_type,Scalar>::PromotedType;
FieldVector<T,SIZE> result;
for (size_type i = 0; i < vector.size(); ++i)
result[i] = vector[i] / scalar;
/// @}
return result;
}
};
/// \name Comparison operators
/// @{
/** \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)
*/
template<class K, int SIZE>
std::istream &operator>> (std::istream& in, FieldVector<K, SIZE>& v)
{
FieldVector<K, SIZE> w;
for (int i = 0; i < SIZE; ++i)
in >> w[i];
if (in)
v = w;
return in;
}
#ifndef DOXYGEN
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
*/
template<class K>
class FieldVector<K, 1> :
public DenseVector< FieldVector<K,1> >
{
K _data;
typedef DenseVector< FieldVector<K,1> > Base;
public:
//! The size of this vector.
constexpr static int dimension = 1;
typedef typename Base::size_type size_type;
/** \brief The type used for references to the vector entry */
typedef K& reference;
/** \brief The type used for const references to the vector entry */
typedef const K& const_reference;
//===== construction
/** \brief Default constructor */
constexpr FieldVector () noexcept
: _data()
{}
//! comparing FieldVectors<1> with scalar for equality
template<Concept::Number S>
friend constexpr bool operator== (const FieldVector& a, const S& b) noexcept
requires(SIZE == 1)
{
return a._data[0] == b;
}
/** \brief Constructor with a given scalar */
template<class T,
std::enable_if_t<std::is_constructible_v<K,T>, int> = 0>
constexpr FieldVector (const T& k) noexcept
: _data(k)
{}
//! comparing FieldVectors<1> with scalar for equality
template<Concept::Number S>
friend constexpr bool operator== (const S& a, const FieldVector& b) noexcept
requires(SIZE == 1)
{
return a == b._data[0];
}
/** \brief Construct from a std::initializer_list */
constexpr FieldVector (const std::initializer_list<K>& l)
//! three-way comparison of FieldVectors
template<class T>
requires (Std::three_way_comparable_with<K,T>)
friend constexpr auto operator<=> (const FieldVector& a, const FieldVector<T,SIZE>& b) noexcept
{
assert(l.size() == 1);
_data = *l.begin();
#if __cpp_lib_three_way_comparison
return a._data <=> b._data;
#else
return Std::lexicographical_compare_three_way(a.begin(), a.end(), b.begin(), b.end());
#endif
}
//! Constructor from static vector of different type
template<class T,
std::enable_if_t<std::is_constructible_v<K,T>, int> = 0>
constexpr FieldVector (const FieldVector<T,1>& x) noexcept
: _data(x[0])
{}
//! three-way comparison of FieldVectors<1> with scalar
template<Concept::Number S>
friend constexpr auto operator<=> (const FieldVector& a, const S& b) noexcept
requires(SIZE == 1)
{
return a._data[0] <=> b;
}
//! Constructor from other dense vector
template<class T,
std::enable_if_t<IsFieldVectorSizeCorrect<T,1>::value, int> = 0,
decltype(std::declval<K&>() = std::declval<const T&>()[0], bool{}) = true>
FieldVector (const DenseVector<T>& x)
//! three-way comparison of FieldVectors<1> with scalar
template<Concept::Number S>
friend constexpr auto operator<=> (const S& a, const FieldVector& b) noexcept
requires(SIZE == 1)
{
assert(x.size() == 1);
_data = x[0];
return a <=> b._data[0];
}
//! copy constructor
constexpr FieldVector (const FieldVector&) = default;
/// @}
//! copy assignment operator
constexpr FieldVector& operator= (const FieldVector&) = default;
//! assignment from static vector of different type
template<class T,
decltype(std::declval<K&>() = std::declval<const T&>(), bool{}) = true>
constexpr FieldVector& operator= (const FieldVector<T,1>& other) noexcept
/// \name Vector space operations
/// @{
//! Vector space multiplication with scalar
template<Concept::Number S>
friend constexpr FieldVector operator* (const FieldVector& a, const S& b) noexcept
{
_data = other[0];
return *this;
FieldVector result;
for (size_type i = 0; i < size(); ++i)
result[i] = a[i] * b;
return result;
}
//! assignment from other dense vector
template<class T,
std::enable_if_t<IsFieldVectorSizeCorrect<T,1>::value, int> = 0,
decltype(std::declval<K&>() = std::declval<const T&>()[0], bool{}) = true>
FieldVector& operator= (const DenseVector<T>& other)
//! Vector space multiplication with scalar
template<Concept::Number S>
friend constexpr FieldVector operator* (const S& a, const FieldVector& b) noexcept
{
assert(other.size() == 1);
_data = other[0];
return *this;
FieldVector result;
for (size_type i = 0; i < size(); ++i)
result[i] = a * b[i];
return result;
}
//! Assignment operator for scalar
template<class T,
decltype(std::declval<K&>() = std::declval<const T&>(), bool{}) = true>
constexpr FieldVector& operator= (const T& k) noexcept
//! Vector space division by scalar
template<Concept::Number S>
friend constexpr FieldVector operator/ (const FieldVector& a, const S& b) noexcept
{
_data = k;
return *this;
FieldVector result;
for (size_type i = 0; i < size(); ++i)
result[i] = a[i] / b;
return result;
}
//===== forward methods to container
static constexpr size_type size () noexcept { return 1; }
reference operator[] ([[maybe_unused]] size_type i)
//! Binary division, when using FieldVector<K,1> like K
template<Concept::Number S>
friend constexpr FieldVector operator/ (const S& a, const FieldVector& b) noexcept
requires(SIZE == 1)
{
DUNE_ASSERT_BOUNDS(i == 0);
return _data;
return FieldVector{a / b[0]};
}
const_reference operator[] ([[maybe_unused]] size_type i) const
//! Binary addition, when using FieldVector<K,1> like K
template<Concept::Number S>
friend constexpr FieldVector operator+ (const FieldVector& a, const S& b) noexcept
requires(SIZE == 1)
{
DUNE_ASSERT_BOUNDS(i == 0);
return _data;
return FieldVector{a[0] + b};
}
//! return pointer to underlying array
constexpr K* data () noexcept
//! Binary addition, when using FieldVector<K,1> like K
template<Concept::Number S>
friend constexpr FieldVector operator+ (const S& a, const FieldVector& b) noexcept
requires(SIZE == 1)
{
return &_data;
return FieldVector{a + b[0]};
}
//! return pointer to underlying array
constexpr const K* data () const noexcept
//! Binary subtraction, when using FieldVector<K,1> like K
template<Concept::Number S>
friend constexpr FieldVector operator- (const FieldVector& a, const S& b) noexcept
requires(SIZE == 1)
{
return &_data;
return FieldVector{a[0] - b};
}
//===== conversion operator
/** \brief Conversion operator */
constexpr operator reference () noexcept { return _data; }
//! Binary subtraction, when using FieldVector<K,1> like K
template<Concept::Number S>
friend constexpr FieldVector operator- (const S& a, const FieldVector& b) noexcept
requires(SIZE == 1)
{
return FieldVector{a - b[0]};
}
/** \brief Const conversion operator */
constexpr operator const_reference () const noexcept { return _data; }
/// @}
};
/* ----- FV / FV ----- */
/* mostly not necessary as these operations are already covered via the cast operator */
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator> (const FieldVector<K,1>& a, const FieldVector<K,1>& b) noexcept
{
return a[0]>b[0];
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator>= (const FieldVector<K,1>& a, const FieldVector<K,1>& b) noexcept
{
return a[0]>=b[0];
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator< (const FieldVector<K,1>& a, const FieldVector<K,1>& b) noexcept
{
return a[0]<b[0];
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator<= (const FieldVector<K,1>& a, const FieldVector<K,1>& b) noexcept
{
return a[0]<=b[0];
}
/* ----- FV / scalar ----- */
//! Binary addition, when using FieldVector<K,1> like K
template<class K>
constexpr FieldVector<K,1> operator+ (const FieldVector<K,1>& a, const K b) noexcept
{
return a[0]+b;
}
//! Binary subtraction, when using FieldVector<K,1> like K
template<class K>
constexpr FieldVector<K,1> operator- (const FieldVector<K,1>& a, const K b) noexcept
{
return a[0]-b;
}
//! Binary multiplication, when using FieldVector<K,1> like K
template<class K>
constexpr FieldVector<K,1> operator* (const FieldVector<K,1>& a, const K b) noexcept
{
return a[0]*b;
}
//! Binary division, when using FieldVector<K,1> like K
template<class K>
constexpr FieldVector<K,1> operator/ (const FieldVector<K,1>& a, const K b) noexcept
{
return a[0]/b;
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator> (const FieldVector<K,1>& a, const K b) noexcept
{
return a[0]>b;
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator>= (const FieldVector<K,1>& a, const K b) noexcept
{
return a[0]>=b;
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator< (const FieldVector<K,1>& a, const K b) noexcept
{
return a[0]<b;
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator<= (const FieldVector<K,1>& a, const K b) noexcept
{
return a[0]<=b;
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator== (const FieldVector<K,1>& a, const K b) noexcept
{
return a[0]==b;
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator!= (const FieldVector<K,1>& a, const K b) noexcept
{
return a[0]!=b;
}
/* ----- scalar / FV ------ */
//! Binary addition, when using FieldVector<K,1> like K
template<class K>
constexpr FieldVector<K,1> operator+ (const K a, const FieldVector<K,1>& b) noexcept
{
return a+b[0];
}
//! Binary subtraction, when using FieldVector<K,1> like K
template<class K>
constexpr FieldVector<K,1> operator- (const K a, const FieldVector<K,1>& b) noexcept
{
return a-b[0];
}
//! Binary multiplication, when using FieldVector<K,1> like K
template<class K>
constexpr FieldVector<K,1> operator* (const K a, const FieldVector<K,1>& b) noexcept
{
return a*b[0];
}
//! Binary division, when using FieldVector<K,1> like K
template<class K>
constexpr FieldVector<K,1> operator/ (const K a, const FieldVector<K,1>& b) noexcept
{
return a/b[0];
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator> (const K a, const FieldVector<K,1>& b) noexcept
{
return a>b[0];
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator>= (const K a, const FieldVector<K,1>& b) noexcept
{
return a>=b[0];
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator< (const K a, const FieldVector<K,1>& b) noexcept
{
return a<b[0];
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator<= (const K a, const FieldVector<K,1>& b) noexcept
{
return a<=b[0];
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator== (const K a, const FieldVector<K,1>& b) noexcept
{
return a==b[0];
}
//! Binary compare, when using FieldVector<K,1> like K
template<class K>
constexpr bool operator!= (const K a, const FieldVector<K,1>& b) noexcept
/** \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)
*/
template<class K, int SIZE>
std::istream& operator>> (std::istream& in, FieldVector<K, SIZE>& v)
{
return a!=b[0];
FieldVector<K, SIZE> w;
for (int i = 0; i < SIZE; ++i)
in >> w[i];
if (in)
v = w;
return in;
}
#endif
/* Overloads for common classification functions */
namespace MathOverloads {
Loading