mirror of
https://gitlab.com/libeigen/eigen.git
synced 2026-04-10 11:34:33 +08:00
release of tvmet (inactive for 2 years and developer unreachable) as the basis for eigen2, because it provides seemingly good expression template mechanisms, we want that, and it would take years to reinvent that wheel. We'll see. So this commit imports the last tvmet release.
165 lines
3.1 KiB
C++
165 lines
3.1 KiB
C++
/*
|
|
* $Id: bad_xpr_const_ref.cc,v 1.1 2003/10/21 19:40:38 opetzold Exp $
|
|
*
|
|
* This example shows the problem on holding references
|
|
* by expressions. On higher optimization levels all things
|
|
* are good. Without optimizations it crashs.
|
|
*/
|
|
|
|
extern "C" int printf(const char*, ...);
|
|
|
|
#ifndef restrict
|
|
#define restrict __restrict__
|
|
#endif
|
|
|
|
template<unsigned Sz> class Vector;
|
|
|
|
struct Fcnl_Assign {
|
|
static inline void apply_on(double& restrict lhs, double rhs) { lhs = rhs; }
|
|
};
|
|
|
|
struct Fcnl_Add {
|
|
static inline double apply_on(double lhs, double rhs) { return lhs + rhs; }
|
|
};
|
|
|
|
template<unsigned Sz, unsigned Stride=0>
|
|
struct MetaVector
|
|
{
|
|
enum {
|
|
doIt = (Stride < (Sz-1)) ? 1 : 0
|
|
};
|
|
|
|
template <class E1, class E2, class Fcnl>
|
|
static inline
|
|
void assign(E1& lhs, const E2& rhs, const Fcnl& fn) {
|
|
fn.apply_on(lhs(Stride), rhs(Stride));
|
|
MetaVector<Sz * doIt, (Stride+1) * doIt>::assign(lhs, rhs, fn);
|
|
}
|
|
};
|
|
|
|
template<>
|
|
struct MetaVector<0,0>
|
|
{
|
|
template <class E1, class E2, class Fcnl>
|
|
static inline void assign(E1&, const E2&, const Fcnl&) { }
|
|
};
|
|
|
|
|
|
template<class E, unsigned Sz>
|
|
struct XprVector
|
|
{
|
|
explicit XprVector(const E& e) : m_expr(e) { }
|
|
|
|
double operator()(unsigned i) const {
|
|
return m_expr(i);
|
|
}
|
|
|
|
template<class E2, class Fcnl>
|
|
void assign_to(E2& e, const Fcnl& fn) const {
|
|
MetaVector<Sz, 0>::assign(e, *this, fn);
|
|
}
|
|
|
|
const E m_expr;
|
|
};
|
|
|
|
|
|
template<unsigned Sz, unsigned Stride=1>
|
|
struct VectorConstReference
|
|
{
|
|
explicit VectorConstReference(const Vector<Sz>& rhs) : m_data(rhs.m_data) { }
|
|
|
|
double operator()(unsigned i) const {
|
|
return m_data[i * Stride];
|
|
}
|
|
|
|
const double* restrict m_data;
|
|
};
|
|
|
|
|
|
template<unsigned Sz>
|
|
struct Vector
|
|
{
|
|
explicit Vector() { }
|
|
|
|
double& restrict operator()(unsigned i) { return m_data[i]; }
|
|
|
|
double operator()(unsigned i) const { return m_data[i]; }
|
|
|
|
typedef VectorConstReference<Sz, 1> ConstReference;
|
|
|
|
ConstReference const_ref() const { return ConstReference(*this); }
|
|
|
|
template<class Fcnl>
|
|
void assign_to(Vector& v, const Fcnl& fn) {
|
|
MetaVector<Sz, 0>::assign(v, *this, fn);
|
|
}
|
|
|
|
template<class E>
|
|
Vector& operator=(const XprVector<E, Sz>& rhs) {
|
|
rhs.assign_to(*this, Fcnl_Assign());
|
|
return *this;
|
|
}
|
|
|
|
double m_data[Sz];
|
|
};
|
|
|
|
|
|
template<class BinOp, class E1, class E2>
|
|
struct XprBinOp
|
|
{
|
|
explicit XprBinOp(const E1& lhs, const E2& rhs)
|
|
: m_lhs(lhs), m_rhs(rhs)
|
|
{ }
|
|
|
|
double operator()(unsigned i) const {
|
|
return BinOp::apply_on(m_lhs(i), m_rhs(i));
|
|
}
|
|
|
|
const E1& m_lhs;
|
|
const E2& m_rhs;
|
|
};
|
|
|
|
|
|
template<unsigned Sz>
|
|
inline
|
|
XprVector<
|
|
XprBinOp<
|
|
Fcnl_Add,
|
|
VectorConstReference<Sz>,
|
|
VectorConstReference<Sz>
|
|
>,
|
|
Sz
|
|
>
|
|
add (const Vector<Sz>& lhs, const Vector<Sz>& rhs) {
|
|
typedef XprBinOp <
|
|
Fcnl_Add,
|
|
VectorConstReference<Sz>,
|
|
VectorConstReference<Sz>
|
|
> expr_type;
|
|
return XprVector<expr_type, Sz>(
|
|
expr_type(lhs.const_ref(), rhs.const_ref()));
|
|
}
|
|
|
|
|
|
int main()
|
|
{
|
|
|
|
Vector<5> v, v1,v2;
|
|
|
|
v1(0) = 1;
|
|
v1(1) = 2;
|
|
v1(2) = 3;
|
|
v1(3) = 4;
|
|
v1(4) = 5;
|
|
|
|
v2(0) = 1;
|
|
v2(1) = 2;
|
|
v2(2) = 3;
|
|
v2(3) = 4;
|
|
v2(4) = 5;
|
|
|
|
v = add(v1, v2);
|
|
|
|
printf("v(0) = %f\n", v(0));
|
|
}
|