]> git.tdb.fi Git - libs/math.git/blob - source/linal/vector.h
11292f7441dae7e7f69cefb58aadb73572f687e4
[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 /**
57 A general mathematical vector.
58 */
59 template<typename T, unsigned N>
60 class Vector: public VectorComponents<T, N>
61 {
62 public:
63         Vector();
64         Vector(const T *);
65         Vector(T, T);
66         Vector(T, T, T);
67         template<typename U>
68         Vector(const Vector<U, N> &);
69
70         Vector &operator*=(T);
71         Vector &operator/=(T);
72         Vector &operator+=(const Vector &);
73         Vector &operator-=(const Vector &);
74
75         T norm() const;
76         Vector &normalize();
77 };
78
79
80 template<typename T, unsigned N>
81 inline Vector<T, N>::Vector()
82 {
83         for(unsigned i=0; i<N; ++i)
84                 (*this)[i] = T();
85 }
86
87 template<typename T, unsigned N>
88 inline Vector<T, N>::Vector(const T *d)
89 {
90         for(unsigned i=0; i<N; ++i)
91                 (*this)[i] = d[i];
92 }
93
94 /* The compiler won't instantiate these unless they are used.  Trying to use
95 them on the wrong class results in an error. */
96 template<typename T, unsigned N>
97 inline Vector<T, N>::Vector(T x_, T y_)
98 {
99         this->VectorComponents<T, 2>::x = x_;
100         this->VectorComponents<T, 2>::y = y_;
101 }
102
103 template<typename T, unsigned N>
104 inline Vector<T, N>::Vector(T x_, T y_, T z_)
105 {
106         this->VectorComponents<T, 3>::x = x_;
107         this->VectorComponents<T, 3>::y = y_;
108         this->VectorComponents<T, 3>::z = z_;
109 }
110
111 template<typename T, unsigned N>
112 template<typename U>
113 inline Vector<T, N>::Vector(const Vector<U, N> &v)
114 {
115         for(unsigned i=0; i<N; ++i)
116                 (*this)[i] = v[i];
117 }
118
119 template<typename T, unsigned N>
120 inline Vector<T, N> &Vector<T, N>::operator*=(T s)
121 {
122         for(unsigned i=0; i<N; ++i)     
123                 (*this)[i] *= s;
124         return *this;
125 }
126
127 template<typename T, unsigned N>
128 inline Vector<T, N> operator*(const Vector<T, N> &v, T s)
129 {
130         Vector<T, N> r(v);
131         return r *= s;
132 }
133
134 template<typename T, unsigned N>
135 inline Vector<T, N> operator*(T s, const Vector<T, N> &v)
136 {
137         return v*s;
138 }
139
140 template<typename T, unsigned N>
141 inline Vector<T, N> &Vector<T, N>::operator/=(T s)
142 {
143         for(unsigned i=0; i<N; ++i)     
144                 (*this)[i] /= s;
145         return *this;
146 }
147
148 template<typename T, unsigned N>
149 inline Vector<T, N> operator/(const Vector<T, N> &v, T s)
150 {
151         Vector<T, N> r(v);
152         return r /= s;
153 }
154
155 template<typename T, unsigned N>
156 inline Vector<T, N> &Vector<T, N>::operator+=(const Vector<T, N> &v)
157 {
158         for(unsigned i=0; i<N; ++i)     
159                 (*this)[i] += v[i];
160         return *this;
161 }
162
163 template<typename T, unsigned N>
164 inline Vector<T, N> operator+(const Vector<T, N> &v1, const Vector<T, N> &v2)
165 {
166         Vector<T, N> r(v1);
167         return r += v2;
168 }
169
170 template<typename T, unsigned N>
171 inline Vector<T, N> &Vector<T, N>::operator-=(const Vector<T, N> &v)
172 {
173         for(unsigned i=0; i<N; ++i)     
174                 (*this)[i] -= v[i];
175         return *this;
176 }
177
178 template<typename T, unsigned N>
179 inline Vector<T, N> operator-(const Vector<T, N> &v1, const Vector<T, N> &v2)
180 {
181         Vector<T, N> r(v1);
182         return r -= v2;
183 }
184
185 template<typename T, unsigned N>
186 inline Vector<T, N> operator-(const Vector<T, N> &v)
187 {
188         Vector<T, N> r(v);
189         for(unsigned i=0; i<N; ++i)
190                 r[i] = -r[i];
191         return r;
192 }
193
194 template<typename T, unsigned N>
195 inline bool operator==(const Vector<T, N> &v, const Vector<T, N> &w)
196 {
197         for(unsigned i=0; i<N; ++i)
198                 if(v[i]!=w[i])
199                         return false;
200         return true;
201 }
202
203 template<typename T, unsigned N>
204 inline T inner_product(const Vector<T, N> &v1, const Vector<T, N> &v2)
205 {
206         T r = T();
207         for(unsigned i=0; i<N; ++i)
208                 r += v1[i]*v2[i];
209         return r;
210 }
211
212 template<typename T, unsigned N>
213 inline T Vector<T, N>::norm() const
214 {
215         return sqrt(inner_product(*this, *this));
216 }
217
218 template<typename T, unsigned N>
219 inline Vector<T, N> &Vector<T, N>::normalize()
220 {
221         return *this /= norm();
222 }
223
224 template<typename T, unsigned N>
225 inline Vector<T, N> normalize(const Vector<T, N> &v)
226 {
227         Vector<T, N> r(v);
228         return r.normalize();
229 }
230
231 template<typename T>
232 inline T dot(const Vector<T, 3> &v1, const Vector<T, 3> &v2)
233 {
234         return inner_product(v1, v2);
235 }
236
237 template<typename T>
238 inline Vector<T, 3> cross(const Vector<T, 3> &v1, const Vector<T, 3> &v2)
239 {
240         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);
241 }
242
243 } // namespace LinAl
244 } // namespace Msp
245
246 #endif