template class TinyContainer { public: typedef W T_Wrapped; TinyContainer() { } TinyContainer(View data) : m_data(data) { } T_Wrapped &unwrap() { return *static_cast(this); } const T_Wrapped &unwrap() const { return *static_cast(this); } protected: mutable View m_data; }; template class TinyBinaryExpr : public TinyContainer< Op, TinyBinaryExpr > { public: typedef typename Left::T_Return T_Return; typedef TinyBinaryExpr T_Expr; T_Expr makeExpr() const { return *this; } TinyBinaryExpr(const Op &op, const Left &left, const Right &right) : TinyContainer< Op, TinyBinaryExpr >(op), m_left(left), m_right(right) { } TinyBinaryExpr(const Left &left, const Right &right) : m_left(left), m_right(right) { } Op op() const { return m_data; } Left left() const { return m_left; } Right right() const { return m_right; } private: Left m_left; Right m_right; }; struct OpAdd { template static T1 apply(const T1 &l, const T2 &r) { return l + r; } }; template inline TinyBinaryExpr operator+(const TinyContainer& l, const TinyContainer& r) { typedef TinyBinaryExpr ret; return ret(l.unwrap().makeExpr(), r.unwrap().makeExpr()); } template inline typename T1::T_Return for_each(const TinyBinaryExpr& node, Functor f) { return Op::apply(for_each(node.left(),f), for_each(node.right(),f)); } template class DenseDataView : public TinyContainer< T*, DenseDataView > { public: typedef T T_Return; typedef DenseDataView T_Expr; T_Expr makeExpr() const { return *this; } T *beginLoc(unsigned i, unsigned j) const { return m_data + S1 * i + S2 * j; } DenseDataView(T *pData) : TinyContainer< T*, DenseDataView >(pData) { } T &offset(unsigned i, unsigned j) { return m_data[S1 * i + S2 * j]; } T offset(unsigned i, unsigned j) const { return m_data[S1 * i + S2 * j]; } template struct Offset { static T &apply(DenseDataView &d) { return d.m_data[S1 * I + S2 * J]; } static T constApply(const DenseDataView &d) { return d.m_data[S1 * I + S2 * J]; } }; }; template struct Eval2 { }; template inline T for_each(const DenseDataView &d, const Eval2 &e) { return d.offset(I, J); } template class DenseData : public TinyContainer< T[Nrows * Ncols], DenseData > { public: typedef T T_Return; typedef DenseDataView T_Expr; T_Expr makeExpr() const { return T_Expr(m_data); } T *beginLoc(unsigned i, unsigned j) const { return &m_data[i + Nrows * j]; } T &operator[](unsigned i) { return m_data[i]; } T operator[](unsigned i) const { return m_data[i]; } T &offset(unsigned i, unsigned j) { return m_data[i + Nrows * j]; } T offset(unsigned i, unsigned j) const { return m_data[i + Nrows * j]; } template struct Offset { static T &apply(DenseData &d) { return d.m_data[I + Nrows * J]; } static T constApply(const DenseData &d) { return d.m_data[I + Nrows * J]; } }; }; template class DiagonalData { public: T &offset(unsigned i, unsigned j) { assert(i == j); return m_data[i]; } T offset(unsigned i, unsigned j) const { return (i == j) ? m_data[i] : T(0); } template struct Offset { static T &apply(DiagonalData &d) { assert(I == J); return d.m_data[I]; } static T constApply(const DiagonalData &d) { return (I == J) ? d.m_data[I] : T(0); } }; private: T m_data[Nrc]; }; template struct InnerLoop { template static inline void eval(LHS &l, const RHS &r) { l.offset(I,J) = for_each(r, Eval2()); InnerLoop::eval(l, r); } }; template struct InnerLoop { template static inline void eval(LHS &, const RHS &) { } }; template struct Loop2 { template static inline void eval(LHS &l, const RHS &r) { InnerLoop::eval(l, r); Loop2::eval(l, r); } }; template struct Loop2 { template static inline void eval(LHS &l, const RHS &r) { } }; template class TinyRange { public: static const unsigned b = Begin; static const unsigned e = End; static const unsigned s = Stride; static const unsigned n = (End - Begin) / Stride + 1; static unsigned index(unsigned i) { return b + s * i; } }; template struct Merge { }; template struct Merge > { static const unsigned s2 = Nrows * Range2::s; typedef DenseDataView type; }; template struct Merge > { static const unsigned s1 = S1 * Range1::s; static const unsigned s2 = S2 * Range2::s; typedef DenseDataView type; }; template > class TinyMatrix : public TinyContainer< Data, TinyMatrix > { public: typedef T T_Return; typedef typename Data::T_Expr T_Expr; typedef TinyContainer< Data, TinyMatrix > T_Base; T_Expr makeExpr() const { return m_data.makeExpr(); } TinyMatrix() { } TinyMatrix(const T &a0, const T &a1, const T &a2, const T &a3, const T &a4, const T &a5) { m_data[0] = a0; m_data[1] = a1; m_data[2] = a2; m_data[3] = a3; m_data[4] = a4; m_data[5] = a5; } TinyMatrix(const T &a0, const T &a1) { m_data[0] = a0; m_data[1] = a1; } TinyMatrix(const Data &d) : T_Base(d) { } T operator()(unsigned i, unsigned j) const { return m_data.offset(i, j); } template TinyMatrix::n, TinyRange::n, typename Merge< TinyRange, TinyRange, Data>::type> operator()(const TinyRange &r1, const TinyRange &r2) { typedef typename Merge< TinyRange, TinyRange, Data>::type T_DataType; typedef TinyMatrix::n, TinyRange::n, T_DataType> T_RetType; return T_RetType(T_DataType(m_data.beginLoc(B1, B2))); } template void operator=(const TinyContainer &rhs) { Loop2<0, 0, Nrows, Ncols>::eval(m_data, rhs.unwrap().makeExpr()); } }; int main() { TinyMatrix a, b(1.0, 2.0, 3.0, 4.0, 5.0, 6.0), c(0.1, 0.2, 0.3, 0.4, 0.5, 0.6), d(0.01, 0.02, 0.03, 0.04, 0.05, 0.06); TinyMatrix e, f(17.0, 48.3); a = b + c + d; a(TinyRange<0,1>(), TinyRange<0,2,2>()); a(TinyRange<0,1>(), TinyRange<0,2,2>()) (TinyRange<0,0>(), TinyRange<0,1>()); e = f + a(TinyRange<0,1>(), TinyRange<0,2,2>()) (TinyRange<0,0>(), TinyRange<0,1>()); }