]> git.tdb.fi Git - libs/math.git/blob - source/linal/vector.h
Add four-component members and constructor to Vector
[libs/math.git] / source / linal / vector.h
1 #ifndef MSP_LINAL_VECTOR_H_
2 #define MSP_LINAL_VECTOR_H_
3
4 #include <algorithm>
5 #include <cmath>
6
7 namespace Msp {
8 namespace LinAl {
9
10 /**
11 Base class to provide the components of a vector.  This is used so that
12 specializations with individual members can be provided in some dimensions.
13 */
14 template<typename T, unsigned N>
15 class VectorComponents
16 {
17 private:
18         T data[N];
19
20 protected:
21         VectorComponents() { }
22
23 public:
24         T &operator[](unsigned i) { return data[i]; }
25         const T &operator[](unsigned i) const { return data[i]; }
26 };
27
28 template<typename T>
29 class VectorComponents<T, 2>
30 {
31 public:
32         T x, y;
33
34 protected:
35         VectorComponents() { }
36
37 public:
38         T &operator[](unsigned i) { return *(&x+i); }
39         const T &operator[](unsigned i) const { return *(&x+i); }
40 };
41
42 template<typename T>
43 class VectorComponents<T, 3>
44 {
45 public:
46         T x, y, z;
47
48 protected:
49         VectorComponents() { }
50
51 public:
52         T &operator[](unsigned i) { return *(&x+i); }
53         const T &operator[](unsigned i) const { return *(&x+i); }
54 };
55
56 template<typename T>
57 class VectorComponents<T, 4>
58 {
59 public:
60         T x, y, z, w;
61
62 protected:
63         VectorComponents() { }
64
65 public:
66         T &operator[](unsigned i) { return *(&x+i); }
67         const T &operator[](unsigned i) const { return *(&x+i); }
68 };
69
70 /**
71 A general mathematical vector.
72 */
73 template<typename T, unsigned N>
74 class Vector: public VectorComponents<T, N>
75 {
76 public:
77         Vector();
78         Vector(const T *);
79         Vector(T, T);
80         Vector(T, T, T);
81         Vector(T, T, T, T);
82         template<typename U>
83         Vector(const Vector<U, N> &);
84
85         Vector &operator*=(T);
86         Vector &operator/=(T);
87         Vector &operator+=(const Vector &);
88         Vector &operator-=(const Vector &);
89
90         T norm() const;
91         Vector &normalize();
92 };
93
94
95 template<typename T, unsigned N>
96 inline Vector<T, N>::Vector()
97 {
98         for(unsigned i=0; i<N; ++i)
99                 (*this)[i] = T();
100 }
101
102 template<typename T, unsigned N>
103 inline Vector<T, N>::Vector(const T *d)
104 {
105         for(unsigned i=0; i<N; ++i)
106                 (*this)[i] = d[i];
107 }
108
109 /* The compiler won't instantiate these unless they are used.  Trying to use
110 them on the wrong class results in an error. */
111 template<typename T, unsigned N>
112 inline Vector<T, N>::Vector(T x_, T y_)
113 {
114         this->VectorComponents<T, 2>::x = x_;
115         this->VectorComponents<T, 2>::y = y_;
116 }
117
118 template<typename T, unsigned N>
119 inline Vector<T, N>::Vector(T x_, T y_, T z_)
120 {
121         this->VectorComponents<T, 3>::x = x_;
122         this->VectorComponents<T, 3>::y = y_;
123         this->VectorComponents<T, 3>::z = z_;
124 }
125
126 template<typename T, unsigned N>
127 inline Vector<T, N>::Vector(T x_, T y_, T z_, T w_)
128 {
129         this->VectorComponents<T, 4>::x = x_;
130         this->VectorComponents<T, 4>::y = y_;
131         this->VectorComponents<T, 4>::z = z_;
132         this->VectorComponents<T, 4>::w = w_;
133 }
134
135 template<typename T, unsigned N>
136 template<typename U>
137 inline Vector<T, N>::Vector(const Vector<U, N> &v)
138 {
139         for(unsigned i=0; i<N; ++i)
140                 (*this)[i] = v[i];
141 }
142
143 template<typename T, unsigned N>
144 inline Vector<T, N> &Vector<T, N>::operator*=(T s)
145 {
146         for(unsigned i=0; i<N; ++i)     
147                 (*this)[i] *= s;
148         return *this;
149 }
150
151 template<typename T, unsigned N>
152 inline Vector<T, N> operator*(const Vector<T, N> &v, T s)
153 {
154         Vector<T, N> r(v);
155         return r *= s;
156 }
157
158 template<typename T, unsigned N>
159 inline Vector<T, N> operator*(T s, const Vector<T, N> &v)
160 {
161         return v*s;
162 }
163
164 template<typename T, unsigned N>
165 inline Vector<T, N> &Vector<T, N>::operator/=(T s)
166 {
167         for(unsigned i=0; i<N; ++i)     
168                 (*this)[i] /= s;
169         return *this;
170 }
171
172 template<typename T, unsigned N>
173 inline Vector<T, N> operator/(const Vector<T, N> &v, T s)
174 {
175         Vector<T, N> r(v);
176         return r /= s;
177 }
178
179 template<typename T, unsigned N>
180 inline Vector<T, N> &Vector<T, N>::operator+=(const Vector<T, N> &v)
181 {
182         for(unsigned i=0; i<N; ++i)     
183                 (*this)[i] += v[i];
184         return *this;
185 }
186
187 template<typename T, unsigned N>
188 inline Vector<T, N> operator+(const Vector<T, N> &v1, const Vector<T, N> &v2)
189 {
190         Vector<T, N> r(v1);
191         return r += v2;
192 }
193
194 template<typename T, unsigned N>
195 inline Vector<T, N> &Vector<T, N>::operator-=(const Vector<T, N> &v)
196 {
197         for(unsigned i=0; i<N; ++i)     
198                 (*this)[i] -= v[i];
199         return *this;
200 }
201
202 template<typename T, unsigned N>
203 inline Vector<T, N> operator-(const Vector<T, N> &v1, const Vector<T, N> &v2)
204 {
205         Vector<T, N> r(v1);
206         return r -= v2;
207 }
208
209 template<typename T, unsigned N>
210 inline Vector<T, N> operator-(const Vector<T, N> &v)
211 {
212         Vector<T, N> r(v);
213         for(unsigned i=0; i<N; ++i)
214                 r[i] = -r[i];
215         return r;
216 }
217
218 template<typename T, unsigned N>
219 inline bool operator==(const Vector<T, N> &v, const Vector<T, N> &w)
220 {
221         for(unsigned i=0; i<N; ++i)
222                 if(v[i]!=w[i])
223                         return false;
224         return true;
225 }
226
227 template<typename T, unsigned N>
228 inline T inner_product(const Vector<T, N> &v1, const Vector<T, N> &v2)
229 {
230         T r = T();
231         for(unsigned i=0; i<N; ++i)
232                 r += v1[i]*v2[i];
233         return r;
234 }
235
236 template<typename T, unsigned N>
237 inline T Vector<T, N>::norm() const
238 {
239         return sqrt(inner_product(*this, *this));
240 }
241
242 template<typename T, unsigned N>
243 inline Vector<T, N> &Vector<T, N>::normalize()
244 {
245         return *this /= norm();
246 }
247
248 template<typename T, unsigned N>
249 inline Vector<T, N> normalize(const Vector<T, N> &v)
250 {
251         Vector<T, N> r(v);
252         return r.normalize();
253 }
254
255 template<typename T>
256 inline T dot(const Vector<T, 3> &v1, const Vector<T, 3> &v2)
257 {
258         return inner_product(v1, v2);
259 }
260
261 template<typename T>
262 inline Vector<T, 3> cross(const Vector<T, 3> &v1, const Vector<T, 3> &v2)
263 {
264         return Vector<T, 3>(v1.y*v2.z-v1.z*v2.y, v1.z*v2.x-v1.x*v2.z, v1.x*v2.y-v1.y*v2.x);
265 }
266
267 } // namespace LinAl
268 } // namespace Msp
269
270 #endif