Commit c341051c authored by Jö Fahlke's avatar Jö Fahlke

Update Proxies for 2.7

Proxies are now tested in dune-common, which uncovered a few missing
operators.  Rather than trying to implement each operator, try to provide a
conversion to value_type, which should work just fine, following the
simd::reference proxies from the Parallelism TS.  Also, it avoids problems
regarding regarding when the left and the right argument of a binary operation
both provide an operator.
parent bcde3631
Pipeline #17579 failed with stage
in 4 minutes and 15 seconds
#ifndef DUNE_VECTORCLASS_VECTORCLASS_HH
#define DUNE_VECTORCLASS_VECTORCLASS_HH
#include <cstddef>
#include <ostream>
#include <type_traits>
#include <utility>
#include <dune/common/math.hh>
#include <dune/common/rangeutilities.hh>
#include <dune/common/typetraits.hh> //needed for AlwaysTrue
#include <dune/common/typetraits.hh>
#include <dune/common/simd/loop.hh>
#include <dune/common/simd/simd.hh>
......@@ -22,132 +24,99 @@ namespace Dune {
template<class V>
class Proxy
{
public:
using value_type = Scalar<V>;
private:
/**reference to the vector**/
V &vec;
/**lane index**/
std::size_t idx;
public:
/**Default constructor**/
Proxy(std::size_t i, V &v) : vec(v) , idx(i) {};
/**Conversion operator**/
operator value_type() const {
return vec[idx];
}
/*Operator overloads*/
//unary ops
template<class T = value_type, typename = std::enable_if_t<!std::is_same<T,bool>::value >>
value_type operator++(int) { return vec[idx]++; }
template<class T = value_type, typename = std::enable_if_t<!std::is_same<T,bool>::value >>
value_type operator--(int) { return vec[idx]--; }
template<class T = value_type, typename = std::enable_if_t<!std::is_same<T,bool>::value >>
Proxy& operator++() { ++(vec[idx]); return *this; }
template<class T = value_type, typename = std::enable_if_t<!std::is_same<T,bool>::value >>
Proxy& operator--() { --(vec[idx]); return *this; }
auto operator!() const { return !(vec[idx]); }
auto operator+() const { return +(vec[idx]); }
auto operator-() const { return -(vec[idx]); }
template<class T = value_type, typename = std::enable_if_t<std::is_integral<T>::value >>
auto operator~() const { return ~(vec[idx]); }
//binary operators
#define DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(OP) \
template<class T> \
auto operator OP(T &&v) const \
-> decltype(vec[idx] OP autoCopy(std::forward<T>(v))) \
{ \
return vec[idx] OP autoCopy(std::forward<T>(v)); \
}
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(+);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(-);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(*);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(/);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(%);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(<<);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(>>);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(<);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(>);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(<=);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(>=);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(==);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(!=);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(&);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(^);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(|);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(&&);
DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP(||);
#undef DUNE_VECTORCLASS_VECTORCLASS_BINARY_OP
//Assignment operators
#define DUNE_VECTORCLASS_VECTORCLASS_ASSIGNMENT_OP(OP) \
template<class T> \
auto operator OP##=(T &&v) -> std::enable_if_t<AlwaysTrue<decltype( \
vec.insert(idx,vec[idx] OP autoCopy(std::forward<T>(v)) ))>::value, Proxy&> \
{ \
vec.insert(idx,vec[idx] OP autoCopy(std::forward<T>(v))); \
return *this; \
}
DUNE_VECTORCLASS_VECTORCLASS_ASSIGNMENT_OP(+);
DUNE_VECTORCLASS_VECTORCLASS_ASSIGNMENT_OP(-);
DUNE_VECTORCLASS_VECTORCLASS_ASSIGNMENT_OP(*);
DUNE_VECTORCLASS_VECTORCLASS_ASSIGNMENT_OP(/);
DUNE_VECTORCLASS_VECTORCLASS_ASSIGNMENT_OP(%);
DUNE_VECTORCLASS_VECTORCLASS_ASSIGNMENT_OP(<<);
DUNE_VECTORCLASS_VECTORCLASS_ASSIGNMENT_OP(>>);
DUNE_VECTORCLASS_VECTORCLASS_ASSIGNMENT_OP(&);
DUNE_VECTORCLASS_VECTORCLASS_ASSIGNMENT_OP(^);
DUNE_VECTORCLASS_VECTORCLASS_ASSIGNMENT_OP(|);
#undef DUNE_VECTORCLASS_VECTORCLASS_ASSIGNMENT_OP
template<class T>
auto operator=(T &&v) -> std::enable_if_t<AlwaysTrue<decltype(
vec.insert(idx, autoCopy(std::forward<T>(v)) ))>::value, Proxy&>
{
vec.insert(idx, autoCopy(std::forward<T>(v)));
return *this;
}
template<class V1, class V2>
friend void swap(Proxy<V1> p1, Proxy<V2> p2);
template<class T>
friend void swap(Proxy p1, T& s2)
{
T tmp = p1.vec[p1.idx];
p1.vec.insert(p1.idx, s2);
s2 = tmp;
}
template<class T>
friend void swap(T& s1, Proxy p2)
{
T tmp = s1;
s1 = p2.vec[p2.idx];
p2.vec.insert(p2.idx, tmp);
}
};
static_assert(std::is_same<V, std::decay_t<V> >::value, "Class Proxy "
"may only be instantiated with unqualified types");
public:
using value_type = Scalar<V>;
private:
static_assert(std::is_arithmetic<value_type>::value,
"Only artihmetic types are supported");
V &vec_;
std::size_t idx_;
public:
Proxy(std::size_t idx, V &vec)
: vec_(vec), idx_(idx)
{ }
Proxy(const Proxy&) = delete;
// allow move construction so we can return proxies from functions in
// C++14
Proxy(Proxy&&) = default;
operator value_type() const { return vec_[idx_]; }
template<class T,
class = std::enable_if_t<std::is_convertible<value_type,
T>::value> >
operator T() const { return value_type(*this); }
// assignment operators
template<class T,
class = decltype(std::declval<value_type&>() =
autoCopy(std::declval<T>()) )>
Proxy operator=(T &&o) &&
{
vec_.insert(idx_, autoCopy(std::forward<T>(o)));
return { idx_, vec_ };
}
#define DUNE_SIMD_VCL_ASSIGNMENT(OP) \
template<class T, \
class = decltype(std::declval<value_type&>() OP##= \
autoCopy(std::declval<T>()) )> \
Proxy operator OP##=(T &&o) && \
{ \
vec_.insert(idx_, vec_[idx_] OP autoCopy(std::forward<T>(o))); \
return { idx_, vec_ }; \
}
DUNE_SIMD_VCL_ASSIGNMENT(*);
DUNE_SIMD_VCL_ASSIGNMENT(/);
DUNE_SIMD_VCL_ASSIGNMENT(%);
DUNE_SIMD_VCL_ASSIGNMENT(+);
DUNE_SIMD_VCL_ASSIGNMENT(-);
DUNE_SIMD_VCL_ASSIGNMENT(<<);
DUNE_SIMD_VCL_ASSIGNMENT(>>);
DUNE_SIMD_VCL_ASSIGNMENT(&);
DUNE_SIMD_VCL_ASSIGNMENT(^);
DUNE_SIMD_VCL_ASSIGNMENT(|);
#undef DUNE_SIMD_VCL_ASSIGNMENT
// unary (prefix) operators
template<class T = value_type,
class = std::enable_if_t<!std::is_same<T, bool>::value> >
Proxy operator++() { ++(vec_[idx_]); return *this; }
template<class T = value_type,
class = std::enable_if_t<!std::is_same<T, bool>::value> >
Proxy operator--() { --(vec_[idx_]); return *this; }
// postfix operators
template<class T = value_type,
class = std::enable_if_t<!std::is_same<T, bool>::value> >
value_type operator++(int) { return vec_[idx_]++; }
template<class T = value_type,
class = std::enable_if_t<!std::is_same<T, bool>::value> >
value_type operator--(int) { return vec_[idx_]--; }
// swap on proxies swaps the proxied vector entries. As such, it
// applies to rvalues of proxies too, not just lvalues
friend void swap(const Proxy &a, const Proxy &b) {
value_type tmp = a.vec_[a.idx_];
a.vec_.insert(a.idx_, b.vec_[b.idx_]);
b.vec_.insert(b.idx_, tmp);
}
friend void swap(value_type &a, const Proxy &b) {
value_type tmp = a;
a = b.vec_[b.idx_];
b.vec_.insert(b.idx_, tmp);
}
friend void swap(const Proxy &a, value_type &b) {
value_type tmp = a.vec_[a.idx_];
a.vec_.insert(a.idx_, b);
b = tmp;
}
template<class V1, class V2>
void swap(Proxy<V1> p1, Proxy<V2> p2)
{
Scalar<V1> tmp = p1.vec[p1.idx];
p1.vec.insert(p1.idx, p2.vec[p2.idx]);
p2.vec.insert(p2.idx, tmp);
}
};
/* true for all vectorclass-types*/
template<class T>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment