// Description: VectorExpression CRTP base class
#ifndef PASTELSYS_VECTOREXPRESSION_H
#define PASTELSYS_VECTOREXPRESSION_H
#include "pastel/sys/vector.h"
#include "pastel/sys/memory_overlaps.h"
#include "pastel/sys/real/real_concept.h"
namespace Pastel
{
template <integer LeftN, integer RightN>
class ResultN
{
public:
static constexpr integer N =
(LeftN == Dynamic) ? RightN : LeftN;
};
template <typename Real, integer N>
class Vector;
template <
typename Real,
integer N>
class VectorConstant;
template <
typename Real,
integer N,
typename Expression>
class VectorNegation;
template <
typename Real,
integer N,
typename LeftExpression,
typename RightExpression>
class VectorAddition;
template <
typename Real,
integer N,
typename LeftExpression,
typename RightExpression>
class VectorSubtraction;
template <
typename Real,
integer N,
typename LeftExpression,
typename RightExpression>
class VectorMultiplication;
template <
typename Real,
integer N,
typename LeftExpression,
typename RightExpression>
class VectorDivision;
template <
typename Real,
integer N,
typename Expression>
class VectorExpression
{
protected:
VectorExpression()
{
}
VectorExpression(const VectorExpression& that)
{
}
VectorExpression& operator=(const VectorExpression& that)
{
return *this;
}
public:
Real operator[](integer index) const
{
return ((const Expression&)*this)[index];
}
integer size() const
{
return ((const Expression&)*this).size();
}
integer n() const
{
return ((const Expression&)*this).size();
}
bool involves(
const void* memoryBegin, const void* memoryEnd) const
{
return ((const Expression&)*this).involves(memoryBegin, memoryEnd);
}
bool evaluateBeforeAssignment(
const void* memoryBegin, const void* memoryEnd) const
{
return ((const Expression&)*this).evaluateBeforeAssignment(memoryBegin, memoryEnd);
}
template <integer RightN, typename RightExpression>
bool operator==(const VectorExpression<Real, RightN, RightExpression>& right) const
{
const Expression& left = (const Expression&)*this;
PENSURE2(left.size() == right.size(), left.size(), right.size());
integer n = size();
for (integer i = 0;i < n;++i)
{
if (!(left[i] == right[i]))
{
return false;
}
}
return true;
}
template <integer RightN, typename RightExpression>
bool operator!=(const VectorExpression<Real, RightN, RightExpression>& right) const
{
return !(*this == right);
}
// Negation
VectorNegation<Real, N, Expression> operator-() const
{
return VectorNegation<Real, N, Expression>((const Expression&)*this);
}
// Summation
template <integer RightN, typename RightExpression>
VectorAddition<Real, ResultN<N, RightN>::N, Expression,
RightExpression>
operator+(const VectorExpression
<Real, RightN, RightExpression>& right) const
{
return VectorAddition
<Real, ResultN<N, RightN>::N, Expression,
RightExpression >
((const Expression&)*this,
(const RightExpression&)right);
}
VectorAddition
<Real, N, Expression, VectorConstant<Real, N> >
operator+(const Real& right) const
{
return VectorAddition
<Real, N, Expression, VectorConstant<Real, N> >
((const Expression&)*this,
VectorConstant<Real, N>(right, size()));
}
friend const VectorAddition
<Real, N, VectorConstant<Real, N>, Expression>
operator+(const Real& left, const VectorExpression& right)
{
return VectorAddition
<Real, N, VectorConstant<Real, N>, Expression>
(VectorConstant<Real, N>(left, right.size()),
(const Expression&)right);
}
// Subtraction
template <integer RightN, typename RightExpression>
VectorSubtraction<Real, ResultN<N, RightN>::N, Expression,
RightExpression>
operator-(const VectorExpression
<Real, RightN, RightExpression>& right) const
{
return VectorSubtraction
<Real, ResultN<N, RightN>::N, Expression,
RightExpression>
((const Expression&)*this,
(const RightExpression&)right);
}
VectorSubtraction
<Real, N, Expression, VectorConstant<Real, N> >
operator-(const Real& right) const
{
return VectorSubtraction
<Real, N, Expression, VectorConstant<Real, N> >
((const Expression&)*this,
VectorConstant<Real, N>(right, size()));
}
friend const VectorSubtraction
<Real, N, VectorConstant<Real, N>, Expression>
operator-(const Real& left, const VectorExpression& right)
{
return VectorSubtraction
<Real, N, VectorConstant<Real, N>, Expression>
(VectorConstant<Real, N>(left, right.size()),
(const Expression&)right);
}
// Multiplication
template <integer RightN, typename RightExpression>
VectorMultiplication<Real, ResultN<N, RightN>::N, Expression,
RightExpression>
operator*(const VectorExpression
<Real, RightN, RightExpression>& right) const
{
return VectorMultiplication
<Real, ResultN<N, RightN>::N, Expression,
RightExpression>
((const Expression&)*this,
(const RightExpression&)right);
}
VectorMultiplication
<Real, N, Expression, VectorConstant<Real, N> >
operator*(const Real& right) const
{
return VectorMultiplication
<Real, N, Expression, VectorConstant<Real, N> >
((const Expression&)*this,
VectorConstant<Real, N>(right, size()));
}
friend const VectorMultiplication
<Real, N, VectorConstant<Real, N>, Expression>
operator*(const Real& left, const VectorExpression& right)
{
return VectorMultiplication
<Real, N, VectorConstant<Real, N>, Expression>
(VectorConstant<Real, N>(left, right.size()),
(const Expression&)right);
}
// Division
template <integer RightN, typename RightExpression>
VectorDivision<Real, ResultN<N, RightN>::N, Expression,
RightExpression>
operator/(const VectorExpression
<Real, RightN, RightExpression>& right) const
{
return VectorDivision
<Real, ResultN<N, RightN>::N, Expression,
RightExpression>
((const Expression&)*this,
(const RightExpression&)right);
}
VectorDivision
<Real, N, Expression, VectorConstant<Real, N> >
operator/(const Real& right) const
{
// You should not optimize here to use
// VectorMultiplication with the reciprocal.
// This is because we also want to support
// the case where Real is an integer.
return VectorDivision
<Real, N, Expression, VectorConstant<Real, N> >
((const Expression&)*this,
VectorConstant<Real, N>(right, size()));
}
friend const VectorDivision
<Real, N, VectorConstant<Real, N>, Expression>
operator/(const Real& left, const VectorExpression& right)
{
return VectorDivision
<Real, N, VectorConstant<Real, N>, Expression>
(VectorConstant<Real, N>(left, right.size()),
(const Expression&)right);
}
template <integer N_ = N, RequiresC<(N_ >= 1)> = 0>
Real x() const
{
return (*this)[0];
}
template <integer N_ = N, RequiresC<(N_ >= 2)> = 0>
Real y() const
{
return (*this)[1];
}
template <integer N_ = N, RequiresC<(N_ >= 3)> = 0>
Real z() const
{
return (*this)[2];
}
template <integer N_ = N, RequiresC<(N_ >= 4)> = 0>
Real w() const
{
return (*this)[3];
}
};
}
#include "pastel/sys/vector/addition_vectorexpression.h"
#include "pastel/sys/vector/constant_vectorexpression.h"
#include "pastel/sys/vector/division_vectorexpression.h"
#include "pastel/sys/vector/lambda_vectorexpression.h"
#include "pastel/sys/vector/multiplication_vectorexpression.h"
#include "pastel/sys/vector/negation_vectorexpression.h"
#include "pastel/sys/vector/subtraction_vectorexpression.h"
#include "pastel/sys/vector/array_vectorexpression.h"
#include "pastel/sys/vector/binary_vectorexpression.h"
#include "pastel/sys/vector/unary_vectorexpression.h"
#include "pastel/sys/vector/point_vectorexpression.h"
#endif