view include/Vector.h @ 6:11e216148d1c

Making progress in Matrix. Reorganized code a bit. Reworked Vector routines to use += -= *=
author Eris Caffee <discordia@eldalin.com>
date Tue, 06 Sep 2011 11:26:39 -0500
parents f6e6f3c8f7eb
children 378862555189
line source
1 #ifndef VECTOR_H_
2 #define VECTOR_H_
4 #include <cmath>
5 #include <string>
7 namespace arda
8 {
9 namespace Vector
10 {
12 ////////////////////////////////////////////////////////////////////////////////
13 // Vectors
14 //
15 // Supported operations on vectors
16 //
17 // assign*() Assign the value of one vector to another.
18 // add*() Add two vectors
19 // cross() Cross product of two 3-space vectors.
20 // dot*() Dot product.
21 // get_angle*() Calculate angle between two vectors.
22 // length*() Length of a vector (the Euclidean norm).
23 // normalize*() Normalize the vector.
24 // proj*() Calculate the projection of one vector onto another.
25 // scale*() Multiply vector by a scalar.
26 // subtract*() A convenience function to avoid writing add(v1, scale(v2, -1))
27 // getstring*() Returns a printable string representation of the vector.
28 //
29 // All functions except getstring are defined inline.
31 typedef int Vector2i[2];
32 typedef float Vector2f[2];
33 typedef double Vector2d[2];
35 typedef int Vector3i[3];
36 typedef float Vector3f[3];
37 typedef double Vector3d[3];
39 typedef int Vector4i[4];
40 typedef float Vector4f[4];
41 typedef double Vector4d[4];
43 //////////////////////////////////////////////////////////////////////////
44 // getstring*(Vector v)
45 // Returns a C string representation of the vector.
46 // This is one of the few non-inline Vector functions.
48 std::string & getstring2v(Vector2i v, std::string & s);
49 std::string & getstring2v(Vector2f v, std::string & s);
50 std::string & getstring2v(Vector2d v, std::string & s);
51 std::string & getstring3v(Vector3i v, std::string & s);
52 std::string & getstring3v(Vector3f v, std::string & s);
53 std::string & getstring3v(Vector3d v, std::string & s);
54 std::string & getstring4v(Vector4i v, std::string & s);
55 std::string & getstring4v(Vector4f v, std::string & s);
56 std::string & getstring4v(Vector4d v, std::string & s);
58 //////////////////////////////////////////////////////////////////////////
59 // scale*(Vector v, scalar s)
60 // Multiply a vector by a scalar.
61 // Returns v so that the result may be passed to other functions.
63 inline int * scale2v(Vector2i v, const int s)
64 { v[0] *= s ; v[1] *= s; return v; }
65 inline int * scale2v(Vector2i v, const float s)
66 { v[0] *= s ; v[1] *= s; return v; }
67 inline int * scale2v(Vector2i v, const double s)
68 { v[0] *= s ; v[1] *= s; return v; }
70 inline float * scale2v(Vector2f v, const int s)
71 { v[0] *= s ; v[1] *= s; return v; }
72 inline float * scale2v(Vector2f v, const float s)
73 { v[0] *= s ; v[1] *= s; return v; }
74 inline float * scale2v(Vector2f v, const double s)
75 { v[0] *= s ; v[1] *= s; return v; }
77 inline double * scale2v(Vector2d v, const int s)
78 { v[0] *= s ; v[1] *= s; return v; }
79 inline double * scale2v(Vector2d v, const float s)
80 { v[0] *= s ; v[1] *= s; return v; }
81 inline double * scale2v(Vector2d v, const double s)
82 { v[0] *= s ; v[1] *= s; return v; }
85 inline int * scale3v(Vector3i v, const int s)
86 { v[0] *= s ; v[1] *= s; v[2] *= s; return v; }
87 inline int * scale3v(Vector3i v, const float s)
88 { v[0] *= s ; v[1] *= s; v[2] *= s; return v; }
89 inline int * scale3v(Vector3i v, const double s)
90 { v[0] *= s ; v[1] *= s; v[2] *= s; return v; }
92 inline float * scale3v(Vector3f v, const int s)
93 { v[0] *= s ; v[1] *= s; v[2] *= s; return v; }
94 inline float * scale3v(Vector3f v, const float s)
95 { v[0] *= s ; v[1] *= s; v[2] *= s; return v; }
96 inline float * scale3v(Vector3f v, const double s)
97 { v[0] *= s ; v[1] *= s; v[2] *= s; return v; }
99 inline double * scale3v(Vector3d v, const int s)
100 { v[0] *= s ; v[1] *= s; v[2] *= s; return v; }
101 inline double * scale3v(Vector3d v, const float s)
102 { v[0] *= s ; v[1] *= s; v[2] *= s; return v; }
103 inline double * scale3v(Vector3d v, const double s)
104 { v[0] *= s ; v[1] *= s; v[2] *= s; return v; }
107 inline int * scale4v(Vector4i v, const int s)
108 { v[0] *= s ; v[1] *= s; v[2] *= s; v[3] *= s; return v; }
109 inline int * scale4v(Vector4i v, const float s)
110 { v[0] *= s ; v[1] *= s; v[2] *= s; v[3] *= s; return v; }
111 inline int * scale4v(Vector4i v, const double s)
112 { v[0] *= s ; v[1] *= s; v[2] *= s; v[3] *= s; return v; }
114 inline float * scale4v(Vector4f v, const int s)
115 { v[0] *= s ; v[1] *= s; v[2] *= s; v[3] *= s; return v; }
116 inline float * scale4v(Vector4f v, const float s)
117 { v[0] *= s ; v[1] *= s; v[2] *= s; v[3] *= s; return v; }
118 inline float * scale4v(Vector4f v, const double s)
119 { v[0] *= s ; v[1] *= s; v[2] *= s; v[3] *= s; return v; }
121 inline double * scale4v(Vector4d v, const int s)
122 { v[0] *= s ; v[1] *= s; v[2] *= s; v[3] *= s; return v; }
123 inline double * scale4v(Vector4d v, const float s)
124 { v[0] *= s ; v[1] *= s; v[2] *= s; v[3] *= s; return v; }
125 inline double * scale4v(Vector4d v, const double s)
126 { v[0] *= s ; v[1] *= s; v[2] *= s; v[3] *= s; return v; }
129 //////////////////////////////////////////////////////////////////////////
130 // dot*(Vector v1, Vector v2)
131 // The dot product of two vectors, which must be the same type
132 // Returns a long for int vectors, a double for floating point vectors.
134 inline long dot2v(Vector2i v1, Vector2i v2)
135 { return (long) v1[0]*v2[0] + (long) v1[1]*v2[1]; }
136 inline double dot2v(Vector2f v1, Vector2f v2)
137 { return (double) v1[0]*v2[0] + (double) v1[1]*v2[1]; }
138 inline double dot2v(Vector2d v1, Vector2d v2)
139 { return v1[0]*v2[0] + v1[1]*v2[1]; }
141 inline long dot3v(Vector3i v1, Vector3i v2)
142 { return (long) v1[0]*v2[0] + (long) v1[1]*v2[1] + (long) v1[2]*v2[2]; }
143 inline double dot3v(Vector3f v1, Vector3f v2)
144 { return (double) v1[0]*v2[0] + (double) v1[1]*v2[1] + (double) v1[2]*v2[2]; }
145 inline double dot3v(Vector3d v1, Vector3d v2)
146 { return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2]; }
148 inline long dot4v(Vector4i v1, Vector4i v2)
149 { return (long) v1[0]*v2[0] + (long) v1[1]*v2[1] + (long) v1[2]*v2[2] + (long) v1[3]*v2[3]; }
150 inline double dot4v(Vector4f v1, Vector4f v2)
151 { return (double) v1[0]*v2[0] + (double) v1[1]*v2[1] + (double) v1[2]*v2[2] + (double) v1[3]*v2[3]; }
152 inline double dot4v(Vector4d v1, Vector4d v2)
153 { return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2] + v1[3]*v2[3]; }
156 //////////////////////////////////////////////////////////////////////////
157 // length*(Vector v)
158 // Get the length of a vector.
159 // Returns a float for float for float vectors, and a double for
160 // int and double vectors.
162 inline double length2v(Vector2i v)
163 { return sqrt((dot2v(v, v))); }
164 inline double length2v(Vector2f v)
165 { return sqrtf((dot2v(v, v))); }
166 inline double length2v(Vector2d v)
167 { return sqrt((dot2v(v, v))); }
169 inline double length3v(Vector3i v)
170 { return sqrt((dot3v(v, v))); }
171 inline double length3v(Vector3f v)
172 { return sqrtf((dot3v(v, v))); }
173 inline double length3v(Vector3d v)
174 { return sqrt((dot3v(v, v))); }
176 inline double length4v(Vector4i v)
177 { return sqrt((dot4v(v, v))); }
178 inline double length4v(Vector4f v)
179 { return sqrtf((dot4v(v, v))); }
180 inline double length4v(Vector4d v)
181 { return sqrt((dot4v(v, v))); }
184 //////////////////////////////////////////////////////////////////////////
185 // add*(Vector v1, Vector v2)
186 // Add v2 to v1.
187 // Returns v1 so that the result may be used in further
188 // calculations.
190 inline int * add2v(Vector2i v1, Vector2i v2)
191 { v1[0] += v2[0]; v1[1] += v2[1]; return v1; }
192 inline float * add2v(Vector2f v1, Vector2f v2)
193 { v1[0] += v2[0]; v1[1] += v2[1]; return v1; }
194 inline double * add2v(Vector2d v1, Vector2d v2)
195 { v1[0] += v2[0]; v1[1] += v2[1]; return v1; }
197 inline int * add3v(Vector3i v1, Vector3i v2)
198 { v1[0] += v2[0]; v1[1] += v2[1]; v1[2] += v2[2]; return v1; }
199 inline float * add3v(Vector3f v1, Vector3f v2)
200 { v1[0] += v2[0]; v1[1] += v2[1]; v1[2] += v2[2]; return v1; }
201 inline double * add3v(Vector3d v1, Vector3d v2)
202 { v1[0] += v2[0]; v1[1] += v2[1]; v1[2] += v2[2]; return v1; }
204 inline int * add4v(Vector4i v1, Vector4i v2)
205 { v1[0] += v2[0]; v1[1] += v2[1]; v1[2] += v2[2]; v1[3] += v2[3]; return v1; }
206 inline float * add4v(Vector4f v1, Vector4f v2)
207 { v1[0] += v2[0]; v1[1] += v2[1]; v1[2] += v2[2]; v1[3] += v2[3]; return v1; }
208 inline double * add4v(Vector4d v1, Vector4d v2)
209 { v1[0] += v2[0]; v1[1] += v2[1]; v1[2] += v2[2]; v1[3] += v2[3]; return v1; }
211 //////////////////////////////////////////////////////////////////////////
212 // normalize*(Vector v)
213 // Normalizes the vecor. Only defined for floating point vectors.
214 // Returns the vector.
216 inline float * normalize2v(Vector2f v)
217 { double l = length2v(v); v[0] /= l; v[1] /= l; return v; }
218 inline double * normalize2v(Vector2d v)
219 { double l = length2v(v); v[0] /= l; v[1] /= l; return v; }
221 inline float * normalize3v(Vector3f v)
222 { double l = length3v(v); v[0] /= l; v[1] /= l; v[2] /= l; return v; }
223 inline double * normalize3v(Vector3d v)
224 { double l = length3v(v); v[0] /= l; v[1] /= l; v[2] /= l; return v; }
226 inline float * normalize4v(Vector4f v)
227 { double l = length4v(v); v[0] /= l; v[1] /= l; v[2] /= l; v[3] /= l; return v; }
228 inline double * normalize4v(Vector4d v)
229 { double l = length4v(v); v[0] /= l; v[1] /= l; v[2] /= l; v[3] /= l; return v; }
231 //////////////////////////////////////////////////////////////////////////
232 // cross(Vector3 v)
233 // Only defined for floating point 3 vectors.
234 // Returns the result vector.
236 inline float * cross(Vector3f v1, Vector3f v2, Vector3f vres)
237 {
238 vres[0] = v1[1]*v2[2] - v2[1]*v1[2];
239 vres[1] = -v1[0]*v2[2] + v2[0]*v1[2];
240 vres[2] = v1[0]*v2[1] - v2[0]*v1[1];
241 return vres;
242 }
244 inline double * cross(Vector3d v1, Vector3d v2, Vector3d vres)
245 {
246 vres[0] = v1[1]*v2[2] - v2[1]*v1[2];
247 vres[1] = -v1[0]*v2[2] + v2[0]*v1[2];
248 vres[2] = v1[0]*v2[1] - v2[0]*v1[1];
249 return vres;
250 }
252 //////////////////////////////////////////////////////////////////////////
253 // get_angle*(Vector3 v1, Vector3 v2)
254 // Returns the angle in radians between the two vectors.
255 //
256 // get_angle[234]n() take pre-normalized vectors as arguments and will
257 // fail otherwise. This version is not defined for interger
258 // vectors since you can't normalize an integer vector.
259 // get_angle[234]() take arbitrary vectors as arguments.
260 //
261 // I started out with two version of get_angle3:
262 // get_angle3_1 implemented as
263 // return acos(dot3v(v1, v2)/(length3v(v1)*length3v(v2)));
264 // get_angle3_2 implemented as
265 // double tmp = dot3v(v1, v2);
266 // return acos(sqrtf(tmp*tmp/(dot3v(v1,v1)*dot3v(v2,v2))));
267 //
268 // I ran timing tests, since I expected the second one - the one I chose to
269 // use, in the end - to be faster since it only resulted in one sqrt call
270 // instead of two. Here are the results
271 //
272 // get_angle3_1 44.753006890 seconds for 500,000,000 iterations.
273 // get_angle3_2 36.940170102 seconds for 500,000,000 iterations.
274 //
275 // Faster? Yes. About 7 nanoseconds vs 9. A ridiculous optimization
276 // to worry about? Eh. I might as well use it.
278 inline double get_angle2n(Vector2f v1, Vector2f v2)
279 { return acos(dot2v(v1, v2)); }
280 inline double get_angle2n(Vector2d v1, Vector2d v2)
281 { return acos(dot2v(v1, v2)); }
282 inline double get_angle2v(Vector2i v1, Vector2i v2)
283 {
284 double tmp = dot2v(v1, v2);
285 return acos(sqrtf(tmp*tmp/(dot2v(v1,v1)*dot2v(v2,v2))));
286 }
287 inline double get_angle2v(Vector2f v1, Vector2f v2)
288 {
289 double tmp = dot2v(v1, v2);
290 return acos(sqrtf(tmp*tmp/(dot2v(v1,v1)*dot2v(v2,v2))));
291 }
292 inline double get_angle2v(Vector2d v1, Vector2d v2)
293 {
294 double tmp = dot2v(v1, v2);
295 return acos(sqrtf(tmp*tmp/(dot2v(v1,v1)*dot2v(v2,v2))));
296 }
298 inline double get_angle3n(Vector3f v1, Vector3f v2)
299 { return acos(dot3v(v1, v2)); }
300 inline double get_angle3n(Vector3d v1, Vector3d v2)
301 { return acos(dot3v(v1, v2)); }
302 inline double get_angle3v(Vector3i v1, Vector3i v2)
303 {
304 double tmp = dot3v(v1, v2);
305 return acos(sqrtf(tmp*tmp/(dot3v(v1,v1)*dot3v(v2,v2))));
306 }
307 inline double get_angle3v(Vector3f v1, Vector3f v2)
308 {
309 double tmp = dot3v(v1, v2);
310 return acos(sqrtf(tmp*tmp/(dot3v(v1,v1)*dot3v(v2,v2))));
311 }
312 inline double get_angle3v(Vector3d v1, Vector3d v2)
313 {
314 double tmp = dot3v(v1, v2);
315 return acos(sqrtf(tmp*tmp/(dot3v(v1,v1)*dot3v(v2,v2))));
316 }
318 inline double get_angle4n(Vector4f v1, Vector4f v2)
319 { return acos(dot4v(v1, v2)); }
320 inline double get_angle4n(Vector4d v1, Vector4d v2)
321 { return acos(dot4v(v1, v2)); }
322 inline double get_angle4v(Vector4i v1, Vector4i v2)
323 {
324 double tmp = dot4v(v1, v2);
325 return acos(sqrtf(tmp*tmp/(dot4v(v1,v1)*dot4v(v2,v2))));
326 }
327 inline double get_angle4v(Vector4f v1, Vector4f v2)
328 {
329 double tmp = dot4v(v1, v2);
330 return acos(sqrtf(tmp*tmp/(dot4v(v1,v1)*dot4v(v2,v2))));
331 }
332 inline double get_angle4v(Vector4d v1, Vector4d v2)
333 {
334 double tmp = dot4v(v1, v2);
335 return acos(sqrtf(tmp*tmp/(dot4v(v1,v1)*dot4v(v2,v2))));
336 }
338 //////////////////////////////////////////////////////////////////////////
339 // subtract*(Vector v1, Vector v2)
340 // Subtract v2 from v1,
341 // Equivalent to add(v1, scale(v2, -1)).
342 // Returns v1 so that the result may be used in further
343 // calculations.
345 inline int * subtract2v(Vector2i v1, Vector2i v2)
346 { v1[0] -= v2[0]; v1[1] -= v2[1]; return v1; }
347 inline float * subtract2v(Vector2f v1, Vector2f v2)
348 { v1[0] -= v2[0]; v1[1] -= v2[1]; return v1; }
349 inline double * subtract2v(Vector2d v1, Vector2d v2)
350 { v1[0] -= v2[0]; v1[1] -= v2[1]; return v1; }
352 inline int * subtract3v(Vector3i v1, Vector3i v2)
353 { v1[0] -= v2[0]; v1[1] -= v2[1]; v1[2] -= v2[2]; return v1; }
354 inline float * subtract3v(Vector3f v1, Vector3f v2)
355 { v1[0] -= v2[0]; v1[1] -= v2[1]; v1[2] -= v2[2]; return v1; }
356 inline double * subtract3v(Vector3d v1, Vector3d v2)
357 { v1[0] -= v2[0]; v1[1] -= v2[1]; v1[2] -= v2[2]; return v1; }
359 inline int * subtract4v(Vector4i v1, Vector4i v2)
360 { v1[0] -= v2[0]; v1[1] -= v2[1]; v1[2] -= v2[2]; v1[3] -= v2[3]; return v1;}
361 inline float * subtract4v(Vector4f v1, Vector4f v2)
362 { v1[0] -= v2[0]; v1[1] -= v2[1]; v1[2] -= v2[2]; v1[3] -= v2[3]; return v1; }
363 inline double * subtract4v(Vector4d v1, Vector4d v2)
364 { v1[0] -= v2[0]; v1[1] -= v2[1]; v1[2] -= v2[2]; v1[3] -= v2[3]; return v1; }
367 //////////////////////////////////////////////////////////////////////////
368 // assign*(Vector v1, Vector v2)
369 // Copies the value of v2 into v1.
370 // Returns v1.
372 inline int * assign2v(Vector2i v1, Vector2i v2)
373 { v1[0] = v2[0]; v1[1] = v2[1]; return v1; }
374 inline float * assign2v(Vector2f v1, Vector2f v2)
375 { v1[0] = v2[0]; v1[1] = v2[1]; return v1; }
376 inline double * assign2v(Vector2d v1, Vector2d v2)
377 { v1[0] = v2[0]; v1[1] = v2[1]; return v1; }
379 inline int * assign3v(Vector3i v1, Vector3i v2)
380 { v1[0] = v2[0]; v1[1] = v2[1]; v1[2] = v2[2]; return v1; }
381 inline float * assign3v(Vector3f v1, Vector3f v2)
382 { v1[0] = v2[0]; v1[1] = v2[1]; v1[2] = v2[2]; return v1; }
383 inline double * assign3v(Vector3d v1, Vector3d v2)
384 { v1[0] = v2[0]; v1[1] = v2[1]; v1[2] = v2[2]; return v1; }
386 inline int * assign4v(Vector4i v1, Vector4i v2)
387 { v1[0] = v2[0]; v1[1] = v2[1]; v1[2] = v2[2]; v1[3] = v2[3]; return v1; }
388 inline float * assign4v(Vector4f v1, Vector4f v2)
389 { v1[0] = v2[0]; v1[1] = v2[1]; v1[2] = v2[2]; v1[3] = v2[3]; return v1; }
390 inline double * assign4v(Vector4d v1, Vector4d v2)
391 { v1[0] = v2[0]; v1[1] = v2[1]; v1[2] = v2[2]; v1[3] = v2[3]; return v1; }
394 //////////////////////////////////////////////////////////////////////////
395 // proj*(Vector v1, Vector v2, Vector vres)
396 // Calculates the projection of v1 onto v2 and returns the result
397 // in vres.
398 // Only defined for floating point vectors.
399 // Returns vres.
401 inline float * proj2v(Vector2f v1, Vector2f v2, Vector2f vres)
402 { assign2v(vres, v2); scale2v(vres, (dot2v(v1, vres)/dot2v(vres,vres))); return vres; }
403 inline double * proj2v(Vector2d v1, Vector2d v2, Vector2d vres)
404 { assign2v(vres, v2); scale2v(vres, (dot2v(v1, vres)/dot2v(vres,vres))); return vres; }
406 inline float * proj3v(Vector3f v1, Vector3f v2, Vector3f vres)
407 { assign3v(vres, v2); scale3v(vres, (dot3v(v1, vres)/dot3v(vres,vres))); return vres; }
408 inline double * proj3v(Vector3d v1, Vector3d v2, Vector3d vres)
409 { assign3v(vres, v2); scale3v(vres, (dot3v(v1, vres)/dot3v(vres,vres))); return vres; }
411 inline float * proj4v(Vector4f v1, Vector4f v2, Vector4f vres)
412 { assign4v(vres, v2); scale4v(vres, (dot4v(v1, vres)/dot4v(vres,vres))); return vres; }
413 inline double * proj4v(Vector4d v1, Vector4d v2, Vector4d vres)
414 { assign4v(vres, v2); scale4v(vres, (dot4v(v1, vres)/dot4v(vres,vres))); return vres; }
416 } // Vector
418 } // namespace arda
420 #endif // VECTOR_H_