// -*- mode: C++; tab-width: 4; indent-tabs-mode: t; -*- vim:ts=4:sw=4 // // Copyright(c) Chong Kai Xiong (descender) // // This file is part of The Plains of Usata. // // The Plains of Usata is licensed under the GNU General Public // License (GPL) version 2. For details, please see the COPYING file // included in the software distribution, or visit // http://www.fsf.org/licenses/gpl.html. // // $Id: vector-template.hpp,v 1.1 2005/01/10 08:14:52 Descender Exp $ #ifndef USATA_VECTOR_TEMPLATE_HPP #define USATA_VECTOR_TEMPLATE_HPP namespace usata { namespace math { class Scalar; class Vector; template class VectorBinaryOp; template struct OperandTraits { typedef const T& Ref; }; template <> struct OperandTraits { typedef Scalar Ref; }; class Scalar { public: Scalar(int x) : m_x(x) {} ~Scalar() {} int operator [] (int index) const { return m_x; } private: int m_x; }; class Vector { public: Vector(int x = 0, int y = 0, int z = 0, int w = 0) { v[0] = x; v[1] = y; v[2] = z; v[3] = w; } template Vector& operator = (const T& expr) { v[0] = expr[0]; v[1] = expr[1]; v[2] = expr[2]; v[3] = expr[3]; return *this; } // lvalue int& operator [] (int index) { return v[index]; } // rvalue int operator [] (int index) const { return v[index]; } friend std::ostream& operator << (std::ostream& out, Vector v) { return out << boost::format("[%1% %2% %3% %4%]") % v[0] % v[1] % v[2] % v[3]; } private: int v[4]; }; template class VectorUnaryOp { public: VectorUnaryOp(const A& a) : m_a(a) {} int operator [] (int index) const { return UnaryOp::eval(m_a[index]); } private: typename OperandTraits::Ref m_a; }; template class VectorBinaryOp { public: VectorBinaryOp(const A& a, const B& b) : m_a(a), m_b(b) {} int operator [] (int index) const { return BinaryOp::eval(m_a[index], m_b[index]); } private: typename OperandTraits::Ref m_a; typename OperandTraits::Ref m_b; }; struct plus { static int eval(int a, int b) { return a + b; } }; struct minus { static int eval(int a, int b) { return a - b; } }; struct multiply { static int eval(int a, int b) { return a * b; } }; struct divide { static int eval(int a, int b) { return a / b; } }; struct negate { static int eval(int a) { return -a; } }; // template typedefs template struct VectorPlus { typedef VectorBinaryOp type; }; template struct VectorMinus { typedef VectorBinaryOp type; }; template struct VectorMultiply { typedef VectorBinaryOp type; }; template struct VectorDivide { typedef VectorBinaryOp type; }; template struct VectorNegate { typedef VectorUnaryOp type; }; // operators template typename VectorPlus::type operator + (const A& a, const B& b) { typedef typename VectorPlus::type PlusResult; return PlusResult(a, b); } template typename VectorMinus::type operator - (const A& a, const B& b) { typedef typename VectorMinus::type MinusResult; return MinusResult(a, b); } template typename VectorNegate::type operator - (const A& a) { typedef typename VectorNegate::type NegateResult; return NegateResult(a); } template typename VectorMultiply::type operator * (const A& a, const B& b) { typedef typename VectorMultiply::type MultiplyResult; return MultiplyResult(a, b); } template typename VectorMultiply::type operator * (const A& a, int b) { typedef typename VectorMultiply::type MultiplyResult; return MultiplyResult(a, Scalar(b)); } template typename VectorMultiply::type operator * (int a, const B& b) { typedef typename VectorMultiply::type MultiplyResult; return MultiplyResult(Scalar(a), b); } template typename VectorDivide::type operator / (const A& a, const B& b) { typedef typename VectorDivide::type DivideResult; return DivideResult(a, b); } template typename VectorDivide::type operator / (const A& a, int b) { typedef typename VectorDivide::type DivideResult; return DivideResult(a, Scalar(b)); } } // namespace math } // namespace usata #endif