]> git.tdb.fi Git - libs/math.git/blob - source/linal/vector.h
767cc88da2d5b5518adc72b00d5f7f55582f8963
[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 #include <ostream>
7
8 namespace Msp {
9 namespace LinAl {
10
11 /**
12 Base class to provide the components of a vector.  This is used so that
13 specializations with individual members can be provided in some dimensions.
14 */
15 template<typename T, unsigned N>
16 class VectorComponents
17 {
18 private:
19         T data[N];
20
21 protected:
22         VectorComponents() { }
23
24 public:
25         T &operator[](unsigned i) { return data[i]; }
26         const T &operator[](unsigned i) const { return data[i]; }
27 };
28
29 template<typename T>
30 class VectorComponents<T, 2>
31 {
32 public:
33         T x, y;
34
35 protected:
36         VectorComponents() { }
37
38 public:
39         T &operator[](unsigned i) { return *(&x+i); }
40         const T &operator[](unsigned i) const { return *(&x+i); }
41 };
42
43 template<typename T>
44 class VectorComponents<T, 3>
45 {
46 public:
47         T x, y, z;
48
49 protected:
50         VectorComponents() { }
51
52 public:
53         T &operator[](unsigned i) { return *(&x+i); }
54         const T &operator[](unsigned i) const { return *(&x+i); }
55 };
56
57 template<typename T>
58 class VectorComponents<T, 4>
59 {
60 public:
61         T x, y, z, w;
62
63 protected:
64         VectorComponents() { }
65
66 public:
67         T &operator[](unsigned i) { return *(&x+i); }
68         const T &operator[](unsigned i) const { return *(&x+i); }
69 };
70
71 /**
72 A general mathematical vector.
73 */
74 template<typename T, unsigned N>
75 class Vector: public VectorComponents<T, N>
76 {
77 public:
78         typedef T ElementType;
79
80         Vector();
81         Vector(const T *);
82
83         /** Constructs a vector from an array of interleaved values.  Intended for
84         use by Matrix row accessor. */
85         Vector(const T *, unsigned);
86
87         Vector(T, T);
88         Vector(T, T, T);
89         Vector(T, T, T, T);
90         template<typename U>
91         Vector(const Vector<U, N> &);
92
93         unsigned size() const { return N; }
94
95         template<unsigned M>
96         Vector<T, M> slice(unsigned) const;
97
98         Vector &operator*=(T);
99         Vector &operator/=(T);
100         Vector &operator+=(const Vector &);
101         Vector &operator-=(const Vector &);
102
103         T norm() const;
104         Vector &normalize();
105 };
106
107
108 template<typename T, unsigned N>
109 inline Vector<T, N>::Vector()
110 {
111         for(unsigned i=0; i<N; ++i)
112                 (*this)[i] = T();
113 }
114
115 template<typename T, unsigned N>
116 inline Vector<T, N>::Vector(const T *d)
117 {
118         for(unsigned i=0; i<N; ++i)
119                 (*this)[i] = d[i];
120 }
121
122 template<typename T, unsigned N>
123 inline Vector<T, N>::Vector(const T *d, unsigned stride)
124 {
125         for(unsigned i=0; i<N; ++i)
126                 (*this)[i] = d[i*stride];
127 }
128
129 /* The compiler won't instantiate these unless they are used.  Trying to use
130 them on the wrong class results in an error. */
131 template<typename T, unsigned N>
132 inline Vector<T, N>::Vector(T x_, T y_)
133 {
134         this->VectorComponents<T, 2>::x = x_;
135         this->VectorComponents<T, 2>::y = y_;
136 }
137
138 template<typename T, unsigned N>
139 inline Vector<T, N>::Vector(T x_, T y_, T z_)
140 {
141         this->VectorComponents<T, 3>::x = x_;
142         this->VectorComponents<T, 3>::y = y_;
143         this->VectorComponents<T, 3>::z = z_;
144 }
145
146 template<typename T, unsigned N>
147 inline Vector<T, N>::Vector(T x_, T y_, T z_, T w_)
148 {
149         this->VectorComponents<T, 4>::x = x_;
150         this->VectorComponents<T, 4>::y = y_;
151         this->VectorComponents<T, 4>::z = z_;
152         this->VectorComponents<T, 4>::w = w_;
153 }
154
155 template<typename T, unsigned N>
156 template<typename U>
157 inline Vector<T, N>::Vector(const Vector<U, N> &v)
158 {
159         for(unsigned i=0; i<N; ++i)
160                 (*this)[i] = v[i];
161 }
162
163 template<typename T, unsigned N>
164 inline Vector<T, N+1> compose(const Vector<T, N> &v, T s)
165 {
166         Vector<T, N+1> r;
167         for(unsigned i=0; i<N; ++i)
168                 r[i] = v[i];
169         r[N] = s;
170         return r;
171 }
172
173 template<typename T, unsigned N>
174 inline Vector<T, N+1> compose(T s, const Vector<T, N> &v)
175 {
176         Vector<T, N+1> r;
177         r[0] = s;
178         for(unsigned i=0; i<N; ++i)
179                 r[i+1] = v[i];
180         return r;
181 }
182
183 template<typename T, unsigned N, unsigned M>
184 inline Vector<T, N+M> compose(const Vector<T, N> &v1, const Vector<T, M> &v2)
185 {
186         Vector<T, N+M> r;
187         for(unsigned i=0; i<N; ++i)
188                 r[i] = v1[i];
189         for(unsigned i=0; i<M; ++i)
190                 r[N+i] = v2[i];
191         return r;
192 }
193
194 template<typename T, unsigned N>
195 template<unsigned M>
196 inline Vector<T, M> Vector<T, N>::slice(unsigned j) const
197 {
198         Vector<T, M> r;
199         for(unsigned i=0; i<M; ++i)
200                 r[i] = (*this)[j+i];
201         return r;
202 }
203
204 template<typename T, unsigned N>
205 inline Vector<T, N> &Vector<T, N>::operator*=(T s)
206 {
207         for(unsigned i=0; i<N; ++i)     
208                 (*this)[i] *= s;
209         return *this;
210 }
211
212 template<typename T, unsigned N>
213 inline Vector<T, N> operator*(const Vector<T, N> &v, T s)
214 {
215         Vector<T, N> r(v);
216         return r *= s;
217 }
218
219 template<typename T, unsigned N>
220 inline Vector<T, N> operator*(T s, const Vector<T, N> &v)
221 {
222         return v*s;
223 }
224
225 template<typename T, unsigned N>
226 inline Vector<T, N> &Vector<T, N>::operator/=(T s)
227 {
228         for(unsigned i=0; i<N; ++i)     
229                 (*this)[i] /= s;
230         return *this;
231 }
232
233 template<typename T, unsigned N>
234 inline Vector<T, N> operator/(const Vector<T, N> &v, T s)
235 {
236         Vector<T, N> r(v);
237         return r /= s;
238 }
239
240 template<typename T, unsigned N>
241 inline Vector<T, N> &Vector<T, N>::operator+=(const Vector<T, N> &v)
242 {
243         for(unsigned i=0; i<N; ++i)     
244                 (*this)[i] += v[i];
245         return *this;
246 }
247
248 template<typename T, unsigned N>
249 inline Vector<T, N> operator+(const Vector<T, N> &v1, const Vector<T, N> &v2)
250 {
251         Vector<T, N> r(v1);
252         return r += v2;
253 }
254
255 template<typename T, unsigned N>
256 inline Vector<T, N> &Vector<T, N>::operator-=(const Vector<T, N> &v)
257 {
258         for(unsigned i=0; i<N; ++i)     
259                 (*this)[i] -= v[i];
260         return *this;
261 }
262
263 template<typename T, unsigned N>
264 inline Vector<T, N> operator-(const Vector<T, N> &v1, const Vector<T, N> &v2)
265 {
266         Vector<T, N> r(v1);
267         return r -= v2;
268 }
269
270 template<typename T, unsigned N>
271 inline Vector<T, N> operator-(const Vector<T, N> &v)
272 {
273         Vector<T, N> r(v);
274         for(unsigned i=0; i<N; ++i)
275                 r[i] = -r[i];
276         return r;
277 }
278
279 template<typename T, unsigned N>
280 inline bool operator==(const Vector<T, N> &v, const Vector<T, N> &w)
281 {
282         for(unsigned i=0; i<N; ++i)
283                 if(v[i]!=w[i])
284                         return false;
285         return true;
286 }
287
288 template<typename T, unsigned N>
289 inline T inner_product(const Vector<T, N> &v1, const Vector<T, N> &v2)
290 {
291         T r = T();
292         for(unsigned i=0; i<N; ++i)
293                 r += v1[i]*v2[i];
294         return r;
295 }
296
297 template<typename T, unsigned N>
298 inline T Vector<T, N>::norm() const
299 {
300         using std::sqrt;
301         return sqrt(inner_product(*this, *this));
302 }
303
304 template<typename T, unsigned N>
305 inline Vector<T, N> &Vector<T, N>::normalize()
306 {
307         return *this /= norm();
308 }
309
310 template<typename T, unsigned N>
311 inline Vector<T, N> normalize(const Vector<T, N> &v)
312 {
313         Vector<T, N> r(v);
314         return r.normalize();
315 }
316
317 template<typename T>
318 inline T dot(const Vector<T, 3> &v1, const Vector<T, 3> &v2)
319 {
320         return inner_product(v1, v2);
321 }
322
323 template<typename T>
324 inline Vector<T, 3> cross(const Vector<T, 3> &v1, const Vector<T, 3> &v2)
325 {
326         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);
327 }
328
329 template<typename T, unsigned N>
330 inline std::ostream &operator<<(std::ostream &s, const Vector<T, N> &v)
331 {
332         s << "Vector" << N << '(';
333         for(unsigned i=0; i<N; ++i)
334         {
335                 if(i)
336                         s << ", ";
337                 s << v[i];
338         }
339         s << ')';
340         return s;
341 }
342
343 } // namespace LinAl
344 } // namespace Msp
345
346 #endif