]> git.tdb.fi Git - libs/math.git/blob - source/linal/vector.h
152c26e66482e943e5837c5ddecc54fc9e7c2fde
[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         typedef T ElementType;
78
79         Vector();
80         Vector(const T *);
81         Vector(T, T);
82         Vector(T, T, T);
83         Vector(T, T, T, T);
84         template<typename U>
85         Vector(const Vector<U, N> &);
86
87         unsigned size() const { return N; }
88
89         template<unsigned M>
90         Vector<T, M> slice(unsigned) const;
91
92         Vector &operator*=(T);
93         Vector &operator/=(T);
94         Vector &operator+=(const Vector &);
95         Vector &operator-=(const Vector &);
96
97         T norm() const;
98         Vector &normalize();
99 };
100
101
102 template<typename T, unsigned N>
103 inline Vector<T, N>::Vector()
104 {
105         for(unsigned i=0; i<N; ++i)
106                 (*this)[i] = T();
107 }
108
109 template<typename T, unsigned N>
110 inline Vector<T, N>::Vector(const T *d)
111 {
112         for(unsigned i=0; i<N; ++i)
113                 (*this)[i] = d[i];
114 }
115
116 /* The compiler won't instantiate these unless they are used.  Trying to use
117 them on the wrong class results in an error. */
118 template<typename T, unsigned N>
119 inline Vector<T, N>::Vector(T x_, T y_)
120 {
121         this->VectorComponents<T, 2>::x = x_;
122         this->VectorComponents<T, 2>::y = y_;
123 }
124
125 template<typename T, unsigned N>
126 inline Vector<T, N>::Vector(T x_, T y_, T z_)
127 {
128         this->VectorComponents<T, 3>::x = x_;
129         this->VectorComponents<T, 3>::y = y_;
130         this->VectorComponents<T, 3>::z = z_;
131 }
132
133 template<typename T, unsigned N>
134 inline Vector<T, N>::Vector(T x_, T y_, T z_, T w_)
135 {
136         this->VectorComponents<T, 4>::x = x_;
137         this->VectorComponents<T, 4>::y = y_;
138         this->VectorComponents<T, 4>::z = z_;
139         this->VectorComponents<T, 4>::w = w_;
140 }
141
142 template<typename T, unsigned N>
143 template<typename U>
144 inline Vector<T, N>::Vector(const Vector<U, N> &v)
145 {
146         for(unsigned i=0; i<N; ++i)
147                 (*this)[i] = v[i];
148 }
149
150 template<typename T, unsigned N>
151 inline Vector<T, N+1> compose(const Vector<T, N> &v, T s)
152 {
153         Vector<T, N+1> r;
154         for(unsigned i=0; i<N; ++i)
155                 r[i] = v[i];
156         r[N] = s;
157         return r;
158 }
159
160 template<typename T, unsigned N>
161 inline Vector<T, N+1> compose(T s, const Vector<T, N> &v)
162 {
163         Vector<T, N+1> r;
164         for(unsigned i=0; i<N; ++i)
165                 r[i] = v[i];
166         r[N] = s;
167         return r;
168 }
169
170 template<typename T, unsigned N, unsigned M>
171 inline Vector<T, N+M> compose(const Vector<T, N> &v1, const Vector<T, M> &v2)
172 {
173         Vector<T, N+M> r;
174         for(unsigned i=0; i<N; ++i)
175                 r[i] = v1[i];
176         for(unsigned i=0; i<M; ++i)
177                 r[N+i] = v2[i];
178         return r;
179 }
180
181 template<typename T, unsigned N>
182 template<unsigned M>
183 inline Vector<T, M> Vector<T, N>::slice(unsigned j) const
184 {
185         Vector<T, M> r;
186         for(unsigned i=0; i<M; ++i)
187                 r[i] = (*this)[j+i];
188         return r;
189 }
190
191 template<typename T, unsigned N>
192 inline Vector<T, N> &Vector<T, N>::operator*=(T s)
193 {
194         for(unsigned i=0; i<N; ++i)     
195                 (*this)[i] *= s;
196         return *this;
197 }
198
199 template<typename T, unsigned N>
200 inline Vector<T, N> operator*(const Vector<T, N> &v, T s)
201 {
202         Vector<T, N> r(v);
203         return r *= s;
204 }
205
206 template<typename T, unsigned N>
207 inline Vector<T, N> operator*(T s, const Vector<T, N> &v)
208 {
209         return v*s;
210 }
211
212 template<typename T, unsigned N>
213 inline Vector<T, N> &Vector<T, N>::operator/=(T s)
214 {
215         for(unsigned i=0; i<N; ++i)     
216                 (*this)[i] /= s;
217         return *this;
218 }
219
220 template<typename T, unsigned N>
221 inline Vector<T, N> operator/(const Vector<T, N> &v, T s)
222 {
223         Vector<T, N> r(v);
224         return r /= s;
225 }
226
227 template<typename T, unsigned N>
228 inline Vector<T, N> &Vector<T, N>::operator+=(const Vector<T, N> &v)
229 {
230         for(unsigned i=0; i<N; ++i)     
231                 (*this)[i] += v[i];
232         return *this;
233 }
234
235 template<typename T, unsigned N>
236 inline Vector<T, N> operator+(const Vector<T, N> &v1, const Vector<T, N> &v2)
237 {
238         Vector<T, N> r(v1);
239         return r += v2;
240 }
241
242 template<typename T, unsigned N>
243 inline Vector<T, N> &Vector<T, N>::operator-=(const Vector<T, N> &v)
244 {
245         for(unsigned i=0; i<N; ++i)     
246                 (*this)[i] -= v[i];
247         return *this;
248 }
249
250 template<typename T, unsigned N>
251 inline Vector<T, N> operator-(const Vector<T, N> &v1, const Vector<T, N> &v2)
252 {
253         Vector<T, N> r(v1);
254         return r -= v2;
255 }
256
257 template<typename T, unsigned N>
258 inline Vector<T, N> operator-(const Vector<T, N> &v)
259 {
260         Vector<T, N> r(v);
261         for(unsigned i=0; i<N; ++i)
262                 r[i] = -r[i];
263         return r;
264 }
265
266 template<typename T, unsigned N>
267 inline bool operator==(const Vector<T, N> &v, const Vector<T, N> &w)
268 {
269         for(unsigned i=0; i<N; ++i)
270                 if(v[i]!=w[i])
271                         return false;
272         return true;
273 }
274
275 template<typename T, unsigned N>
276 inline T inner_product(const Vector<T, N> &v1, const Vector<T, N> &v2)
277 {
278         T r = T();
279         for(unsigned i=0; i<N; ++i)
280                 r += v1[i]*v2[i];
281         return r;
282 }
283
284 template<typename T, unsigned N>
285 inline T Vector<T, N>::norm() const
286 {
287         using std::sqrt;
288         return sqrt(inner_product(*this, *this));
289 }
290
291 template<typename T, unsigned N>
292 inline Vector<T, N> &Vector<T, N>::normalize()
293 {
294         return *this /= norm();
295 }
296
297 template<typename T, unsigned N>
298 inline Vector<T, N> normalize(const Vector<T, N> &v)
299 {
300         Vector<T, N> r(v);
301         return r.normalize();
302 }
303
304 template<typename T>
305 inline T dot(const Vector<T, 3> &v1, const Vector<T, 3> &v2)
306 {
307         return inner_product(v1, v2);
308 }
309
310 template<typename T>
311 inline Vector<T, 3> cross(const Vector<T, 3> &v1, const Vector<T, 3> &v2)
312 {
313         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);
314 }
315
316 } // namespace LinAl
317 } // namespace Msp
318
319 #endif