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