// (c) Copyright 2010 Terry Golubiewski, all rights reserved. #ifndef CARTESIAN_VECTOR_H #define CARTESIAN_VECTOR_H #pragma once #include #include #include #include #include #include namespace cartesian { struct uninitialized_t { }; static const uninitialized_t uninitialized = { }; template class vector { public: static const int dim = Dim; typedef Rep rep; boost::array coord; vector(uninitialized_t) { } vector() { coord.fill(rep()); } vector(const vector& v) : coord(v.coord) { } vector& operator=(const vector& v) { coord = v.coord; return *this; } template vector(const vector& v) { coord = v.coord; } template vector& operator=(const vector& v) { coord = v.coord; return *this; } template vector(InIter first_, InIter last_) { using namespace std; if (distance(first_, last_) != dim) { std::out_of_range e("cartesian::vector<> invalid input iterators"); boost::throw_exception(e); } copy(first_, last_, coord.begin()); } // iterator initialization template const rep& get() const { return coord[N]; } template rep& get() { return coord[N]; } template void set(rep v) { coord[N] = v; } rep& operator[](int i) { return coord[i]; } const rep& operator[](int i) const { return coord[i]; } template vector& operator+=(const vector& rhs) { for (int i=0; i!=dim; ++i) coord[i] += rhs[i]; return *this; } template vector& operator-=(const vector& rhs) { for (int i=0; i!=dim; ++i) coord[i] -= rhs[i]; return *this; } vector& operator*=(const rep& rhs) { for (int i=0; i!=dim; ++i) coord[i] *= rhs; return *this; } vector& operator/=(const rep& rhs) { for (int i=0; i!=dim; ++i) coord[i] /= rhs; return *this; } friend vector operator*(vector lhs, const rep& rhs) { return lhs *= rhs; } friend vector operator/(vector lhs, const rep& rhs) { return lhs /= rhs; } friend rep abs_squared(const vector& v) { rep sum = v[0] * v[0]; for (int i=1; i!=dim; ++i) { const rep& x = v[i]; sum += x * x; } return sum; } // abs_squared friend rep abs(const vector& v) { using namespace std; return sqrt(abs_squared(v)); } }; // vector template inline vector::type> operator+(const vector&lhs, const vector& rhs) { vector::type> rval(lhs); return rval += rhs; } template inline vector::type> operator-(const vector&lhs, const vector& rhs) { vector::type> rval(lhs); return rval -= rhs; } template inline typename std0x::common_type::type operator*(const vector& lhs, const vector& rhs) { typedef typename std0x::common_type::type return_type; return_type sum = lhs[0] * rhs[0]; for (int i=1; i!=dim; ++i) sum += lhs[i] * rhs[i]; return sum; } // dot product template inline bool operator==(const vector& lhs, const vector& rhs) { for (int i=0; i!=dim; ++i) { if (lhs[i] != rhs[i]) return false; } return true; } template inline bool operator!=(const vector& lhs, const vector& rhs) { return !(lhs == rhs); } // Is it a good idea to order vectors based on their magnitude? template inline bool operator<(const vector& lhs, const vector& rhs) { return abs_squared(lhs) < abs_squared(rhs); } template inline bool operator>(const vector& lhs, const vector& rhs) { return rhs < lhs; } template inline bool operator>=(const vector& lhs, const vector& rhs) { return !(lhs < rhs); } template inline bool operator<=(const vector& lhs, const vector& rhs) { return !(rhs < lhs); } template inline vector<1, Rep> make_vector(Rep x) { vector<1, Rep> v(uninitialized); v.set<0>(x); return v; } // make_vector template inline vector<2, typename std0x::common_type::type> make_vector(T1 x, T2 y) { vector<2, typename std0x::common_type::type> v(uninitialized); v.set<0>(x); v.set<1>(y); return v; } // make_vector template struct common_type3 { typedef typename std0x::common_type::type >::type type; }; // common_type3 template inline vector<3, typename common_type3::type> make_vector(T1 x, T2 y, T3 z) { vector<3, typename common_type3::type> v(uninitialized); v.set<0>(x); v.set<1>(y); v.set<2>(z); return v; } // make_vector template inline vector<3, typename std0x::common_type::type> cross_product(const vector<3, T1>& a, const vector<3, T2>& b) { return make_vector(a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]); } // cross_product class vector2d: public vector<2, double> { public: vector2d(double dx, double dy) : vector<2, double>(make_vector(dx, dy)) { } template vector2d(vector<2, U> v) : vector<2, double>(v) { } double& x() { return get<0>(); } double& y() { return get<1>(); } const double& x() const { return get<0>(); } const double& y() const { return get<1>(); } }; // vector2d class vector3d: public vector<3, double> { public: vector3d(double dx, double dy, double dz=0) : vector<3, double>(make_vector(dx, dy, dz)) { } template vector3d(vector<3, U> v) : vector<3, double>(v) { } double& x() { return get<0>(); } double& y() { return get<1>(); } double& z() { return get<2>(); } const double& x() const { return get<0>(); } const double& y() const { return get<1>(); } const double& z() const { return get<2>(); } }; // vector3d } // cartesian #endif