X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Flinal%2Fvector.h;h=31597d4282410e2606590eaea2faa6d3c22c2cd9;hb=0a8781509bafe347b9c32f1106891eac18354965;hp=392e3a12772dcdc6e3b9f12dba937c7d38779e29;hpb=b60ee0fb060790277bfc68722f85a137a58ad771;p=libs%2Fmath.git diff --git a/source/linal/vector.h b/source/linal/vector.h index 392e3a1..31597d4 100644 --- a/source/linal/vector.h +++ b/source/linal/vector.h @@ -3,27 +3,102 @@ #include #include +#include namespace Msp { namespace LinAl { /** -A general mathematical vector. +Base class to provide the components of a vector. This is used so that +specializations with individual members can be provided in some dimensions. */ template -class Vector +class VectorComponents { -protected: +private: T data[N]; +protected: + VectorComponents() { } + +public: + T &operator[](unsigned i) { return data[i]; } + const T &operator[](unsigned i) const { return data[i]; } +}; + +template +class VectorComponents +{ +public: + T x, y; + +protected: + VectorComponents() { } + +public: + T &operator[](unsigned i) { return *(&x+i); } + const T &operator[](unsigned i) const { return *(&x+i); } +}; + +template +class VectorComponents +{ +public: + T x, y, z; + +protected: + VectorComponents() { } + +public: + T &operator[](unsigned i) { return *(&x+i); } + const T &operator[](unsigned i) const { return *(&x+i); } +}; + +template +class VectorComponents +{ public: + T x, y, z, w; + +protected: + VectorComponents() { } + +public: + T &operator[](unsigned i) { return *(&x+i); } + const T &operator[](unsigned i) const { return *(&x+i); } +}; + +/** +A general mathematical vector. +*/ +template +class Vector: public VectorComponents +{ +public: + typedef T ElementType; + Vector(); - Vector(const T *d); + Vector(const T *); + + /** Constructs a vector from an array of interleaved values. Intended for + use by Matrix row accessor. */ + Vector(const T *, unsigned); + +#if __cplusplus >= 201103L + template + Vector(T, Args...); +#else + Vector(T, T); + Vector(T, T, T); + Vector(T, T, T, T); +#endif template - Vector(const Vector &v); + Vector(const Vector &); - T &operator[](unsigned i) { return data[i]; } - const T &operator[](unsigned i) const { return data[i]; } + unsigned size() const { return N; } + + template + Vector slice(unsigned) const; Vector &operator*=(T); Vector &operator/=(T); @@ -38,27 +113,117 @@ public: template inline Vector::Vector() { - std::fill(data, data+N, T()); + for(unsigned i=0; i inline Vector::Vector(const T *d) { - std::copy(d, d+N, data); + for(unsigned i=0; i +inline Vector::Vector(const T *d, unsigned stride) +{ + for(unsigned i=0; i= 201103L +template +template +inline Vector::Vector(T x_, Args... v) +{ + static_assert(1+sizeof...(v)==N, "Incorrect number of arguments in Vector constructor"); + (*this)[0] = x_; + unsigned i = 1; + for(auto c: std::initializer_list { static_cast(v)... }) + (*this)[i++] = c; +} +#else +/* The compiler won't instantiate these unless they are used. Trying to use +them on the wrong class results in an error. */ +template +inline Vector::Vector(T x_, T y_) +{ + this->VectorComponents::x = x_; + this->VectorComponents::y = y_; +} + +template +inline Vector::Vector(T x_, T y_, T z_) +{ + this->VectorComponents::x = x_; + this->VectorComponents::y = y_; + this->VectorComponents::z = z_; +} + +template +inline Vector::Vector(T x_, T y_, T z_, T w_) +{ + this->VectorComponents::x = x_; + this->VectorComponents::y = y_; + this->VectorComponents::z = z_; + this->VectorComponents::w = w_; } +#endif template template inline Vector::Vector(const Vector &v) { - std::copy(v.data, v.data+N, data); + for(unsigned i=0; i +inline Vector compose(const Vector &v, T s) +{ + Vector r; + for(unsigned i=0; i +inline Vector compose(T s, const Vector &v) +{ + Vector r; + r[0] = s; + for(unsigned i=0; i +inline Vector compose(const Vector &v1, const Vector &v2) +{ + Vector r; + for(unsigned i=0; i +template +inline Vector Vector::slice(unsigned j) const +{ + Vector r; + for(unsigned i=0; i inline Vector &Vector::operator*=(T s) { for(unsigned i=0; i inline Vector &Vector::operator/=(T s) { for(unsigned i=0; i inline Vector &Vector::operator+=(const Vector &v) { for(unsigned i=0; i inline Vector &Vector::operator-=(const Vector &v) { for(unsigned i=0; i &v1, const Vector &v2) template inline T Vector::norm() const { + using std::sqrt; return sqrt(inner_product(*this, *this)); } @@ -166,6 +332,32 @@ inline Vector normalize(const Vector &v) return r.normalize(); } +template +inline T dot(const Vector &v1, const Vector &v2) +{ + return inner_product(v1, v2); +} + +template +inline Vector cross(const Vector &v1, const Vector &v2) +{ + return Vector(v1.y*v2.z-v1.z*v2.y, v1.z*v2.x-v1.x*v2.z, v1.x*v2.y-v1.y*v2.x); +} + +template +inline std::ostream &operator<<(std::ostream &s, const Vector &v) +{ + s << "Vector" << N << '('; + for(unsigned i=0; i