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