coord: use consistent technique for assignment operators
This commit is contained in:
parent
e2f0d23a6d
commit
959617277f
128
coord/ops.hpp
128
coord/ops.hpp
@ -48,35 +48,78 @@ namespace util {
|
|||||||
// specific template template parameters. but the introduction of
|
// specific template template parameters. but the introduction of
|
||||||
// coordinate types that do not expose size or type information as template
|
// coordinate types that do not expose size or type information as template
|
||||||
// parameters we can't rely on this mechanism anymore.
|
// parameters we can't rely on this mechanism anymore.
|
||||||
|
|
||||||
template <typename, typename, typename=void>
|
template <typename, typename, typename=void>
|
||||||
struct ops {};
|
struct assignment {};
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// vector operators
|
template <typename CoordA, typename CoordB>
|
||||||
template <typename ValueA, typename ValueB>
|
struct assignment<
|
||||||
struct ops<
|
CoordA,
|
||||||
ValueA,
|
CoordB,
|
||||||
ValueB,
|
|
||||||
std::enable_if_t<
|
std::enable_if_t<
|
||||||
is_coord_v<ValueA> &&
|
is_coord_v<CoordA> &&
|
||||||
is_coord_v<ValueB> &&
|
is_coord_v<CoordB> &&
|
||||||
arity<ValueA>::value == arity<ValueB>::value
|
arity_v<CoordA> == arity_v<CoordB> &&
|
||||||
|
std::is_same_v<
|
||||||
|
typename CoordA::value_type,
|
||||||
|
std::common_type_t<
|
||||||
|
typename CoordA::value_type,
|
||||||
|
typename CoordB::value_type
|
||||||
|
>
|
||||||
|
>
|
||||||
,
|
,
|
||||||
void
|
void
|
||||||
>
|
>
|
||||||
> {
|
> {
|
||||||
template <typename OpT>
|
template <typename OperationT>
|
||||||
static constexpr ValueA&
|
static constexpr CoordA&
|
||||||
assignment (OpT op, ValueA &a, ValueB b)
|
eval (OperationT &&op, CoordA &a, const CoordB &b)
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < ValueA::elements; ++i)
|
for (std::size_t i = 0; i < CoordA::elements; ++i)
|
||||||
a[i] = op (a[i], b[i]);
|
a[i] = op (a[i], b[i]);
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// vector-scalar operations
|
||||||
|
template <
|
||||||
|
typename CoordT,
|
||||||
|
typename ScalarT
|
||||||
|
>
|
||||||
|
struct assignment<
|
||||||
|
CoordT,
|
||||||
|
ScalarT,
|
||||||
|
std::enable_if_t<
|
||||||
|
is_coord_v<CoordT> &&
|
||||||
|
!is_coord_v<ScalarT> &&
|
||||||
|
has_scalar_op_v<CoordT> &&
|
||||||
|
std::is_same_v<
|
||||||
|
typename CoordT::value_type,
|
||||||
|
std::common_type_t<
|
||||||
|
typename CoordT::value_type,
|
||||||
|
ScalarT
|
||||||
|
>
|
||||||
|
>
|
||||||
|
,
|
||||||
|
void
|
||||||
|
>
|
||||||
|
> {
|
||||||
|
// we allow scalar types which can be naturally promoted to the vector's
|
||||||
|
// value_type
|
||||||
|
template <typename OperationT>
|
||||||
|
static constexpr CoordT&
|
||||||
|
eval (OperationT &&op, CoordT &coord, const ScalarT scalar)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < CoordT::elements; ++i)
|
||||||
|
coord[i] = op (coord[i], scalar);
|
||||||
|
return coord;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
/// create a coord from supplied arguments, optionally specifying the
|
/// create a coord from supplied arguments, optionally specifying the
|
||||||
/// underlying type.
|
/// underlying type.
|
||||||
@ -125,6 +168,7 @@ namespace util {
|
|||||||
struct arithmetic {};
|
struct arithmetic {};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
template <typename CoordA, typename CoordB>
|
template <typename CoordA, typename CoordB>
|
||||||
struct arithmetic<
|
struct arithmetic<
|
||||||
CoordA,
|
CoordA,
|
||||||
@ -155,6 +199,7 @@ namespace util {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
template <typename CoordT, typename ScalarT>
|
template <typename CoordT, typename ScalarT>
|
||||||
struct arithmetic<
|
struct arithmetic<
|
||||||
CoordT,
|
CoordT,
|
||||||
@ -177,6 +222,7 @@ namespace util {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
template <typename ScalarT, typename CoordT>
|
template <typename ScalarT, typename CoordT>
|
||||||
struct arithmetic<
|
struct arithmetic<
|
||||||
ScalarT,
|
ScalarT,
|
||||||
@ -200,46 +246,6 @@ namespace util {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
// vector-scalar operations
|
|
||||||
template <
|
|
||||||
typename CoordT,
|
|
||||||
typename ScalarT
|
|
||||||
>
|
|
||||||
struct ops<
|
|
||||||
CoordT,
|
|
||||||
ScalarT,
|
|
||||||
std::enable_if_t<
|
|
||||||
is_coord_v<CoordT> &&
|
|
||||||
!is_coord_v<ScalarT> &&
|
|
||||||
has_scalar_op_v<CoordT>
|
|
||||||
>
|
|
||||||
> {
|
|
||||||
// we allow scalar types which can be naturally promoted to the vector's
|
|
||||||
// value_type
|
|
||||||
template <
|
|
||||||
typename OpT,
|
|
||||||
typename = std::enable_if_t<
|
|
||||||
std::is_same_v<
|
|
||||||
typename CoordT::value_type,
|
|
||||||
std::common_type_t<
|
|
||||||
typename CoordT::value_type,
|
|
||||||
ScalarT
|
|
||||||
>
|
|
||||||
>,
|
|
||||||
void
|
|
||||||
>
|
|
||||||
>
|
|
||||||
static constexpr CoordT&
|
|
||||||
assignment (OpT &&op, CoordT &c, const ScalarT s)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < CoordT::elements; ++i)
|
|
||||||
c[i] = op (c[i], s);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
template <
|
template <
|
||||||
typename A,
|
typename A,
|
||||||
@ -321,10 +327,10 @@ namespace util {
|
|||||||
constexpr auto
|
constexpr auto
|
||||||
operator += (A &&a, B &&b)
|
operator += (A &&a, B &&b)
|
||||||
{
|
{
|
||||||
return ops<
|
return assignment<
|
||||||
std::decay_t<A>,
|
std::decay_t<A>,
|
||||||
std::decay_t<B>
|
std::decay_t<B>
|
||||||
>::template assignment (std::plus{}, a, b);
|
>::eval (std::plus{}, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -340,10 +346,10 @@ namespace util {
|
|||||||
constexpr auto
|
constexpr auto
|
||||||
operator -= (A &&a, B &&b)
|
operator -= (A &&a, B &&b)
|
||||||
{
|
{
|
||||||
return ops<
|
return assignment<
|
||||||
std::decay_t<A>,
|
std::decay_t<A>,
|
||||||
std::decay_t<B>
|
std::decay_t<B>
|
||||||
>::template assignment (std::minus{}, a, b);
|
>::eval (std::minus{}, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -359,10 +365,10 @@ namespace util {
|
|||||||
constexpr auto
|
constexpr auto
|
||||||
operator *= (A &&a, B &&b)
|
operator *= (A &&a, B &&b)
|
||||||
{
|
{
|
||||||
return ops<
|
return assignment<
|
||||||
std::decay_t<A>,
|
std::decay_t<A>,
|
||||||
std::decay_t<B>
|
std::decay_t<B>
|
||||||
>::template assignment (std::multiplies{}, a, b);
|
>::eval (std::multiplies{}, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -378,10 +384,10 @@ namespace util {
|
|||||||
constexpr auto
|
constexpr auto
|
||||||
operator /= (A &&a, B &&b)
|
operator /= (A &&a, B &&b)
|
||||||
{
|
{
|
||||||
return ops<
|
return assignment<
|
||||||
std::decay_t<A>,
|
std::decay_t<A>,
|
||||||
std::decay_t<B>
|
std::decay_t<B>
|
||||||
>::template assignment (std::divides{}, a, b);
|
>::eval (std::divides{}, a, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user