source: ThirdParty/mpqc_open/src/lib/util/render/algebra3.cc@ 398fcd

Action_Thermostats Add_AtomRandomPerturbation Add_RotateAroundBondAction Add_SelectAtomByNameAction Adding_Graph_to_ChangeBondActions Adding_MD_integration_tests Adding_StructOpt_integration_tests AutomationFragmentation_failures Candidate_v1.6.0 Candidate_v1.6.1 ChangeBugEmailaddress ChangingTestPorts ChemicalSpaceEvaluator Combining_Subpackages Debian_Package_split Debian_package_split_molecuildergui_only Disabling_MemDebug Docu_Python_wait EmpiricalPotential_contain_HomologyGraph_documentation Enable_parallel_make_install Enhance_userguide Enhanced_StructuralOptimization Enhanced_StructuralOptimization_continued Example_ManyWaysToTranslateAtom Exclude_Hydrogens_annealWithBondGraph FitPartialCharges_GlobalError Fix_ChronosMutex Fix_StatusMsg Fix_StepWorldTime_single_argument Fix_Verbose_Codepatterns ForceAnnealing_goodresults ForceAnnealing_oldresults ForceAnnealing_tocheck ForceAnnealing_with_BondGraph ForceAnnealing_with_BondGraph_continued ForceAnnealing_with_BondGraph_continued_betteresults ForceAnnealing_with_BondGraph_contraction-expansion GeometryObjects Gui_displays_atomic_force_velocity IndependentFragmentGrids_IntegrationTest JobMarket_RobustOnKillsSegFaults JobMarket_StableWorkerPool JobMarket_unresolvable_hostname_fix ODR_violation_mpqc_open PartialCharges_OrthogonalSummation PythonUI_with_named_parameters QtGui_reactivate_TimeChanged_changes Recreated_GuiChecks RotateToPrincipalAxisSystem_UndoRedo StoppableMakroAction Subpackage_levmar Subpackage_vmg ThirdParty_MPQC_rebuilt_buildsystem TremoloParser_IncreasedPrecision TremoloParser_MultipleTimesteps Ubuntu_1604_changes stable
Last change on this file since 398fcd was 860145, checked in by Frederik Heber <heber@…>, 8 years ago

Merge commit '0b990dfaa8c6007a996d030163a25f7f5fc8a7e7' as 'ThirdParty/mpqc_open'

  • Property mode set to 100644
File size: 24.1 KB
Line 
1#include <util/misc/math.h>
2#include <util/render/algebra3.h>
3#include <util/misc/exenv.h>
4#include <ctype.h>
5
6using namespace std;
7using namespace sc;
8
9// min-max macros
10#define MIN(A,B) ((A) < (B) ? (A) : (B))
11#define MAX(A,B) ((A) > (B) ? (A) : (B))
12
13// error handling macro
14#define V_ERROR(E) { ExEnv::errn() << E; exit(1); }
15
16/****************************************************************
17* *
18* vec2 Member functions *
19* *
20****************************************************************/
21
22// CONSTRUCTORS
23
24vec2::vec2() {}
25
26vec2::vec2(const double x, const double y)
27{ n[VX] = x; n[VY] = y; }
28
29vec2::vec2(const double d)
30{ n[VX] = n[VY] = d; }
31
32vec2::vec2(const vec2& v)
33{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; }
34
35vec2::vec2(const vec3& v) // it is up to caller to avoid divide-by-zero
36{ n[VX] = v.n[VX]/v.n[VZ]; n[VY] = v.n[VY]/v.n[VZ]; };
37
38vec2::vec2(const vec3& v, int dropAxis) {
39 switch (dropAxis) {
40 case VX: n[VX] = v.n[VY]; n[VY] = v.n[VZ]; break;
41 case VY: n[VX] = v.n[VX]; n[VY] = v.n[VZ]; break;
42 default: n[VX] = v.n[VX]; n[VY] = v.n[VY]; break;
43 }
44}
45
46
47// ASSIGNMENT OPERATORS
48
49vec2& vec2::operator = (const vec2& v)
50{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; return *this; }
51
52vec2& vec2::operator += ( const vec2& v )
53{ n[VX] += v.n[VX]; n[VY] += v.n[VY]; return *this; }
54
55vec2& vec2::operator -= ( const vec2& v )
56{ n[VX] -= v.n[VX]; n[VY] -= v.n[VY]; return *this; }
57
58vec2& vec2::operator *= ( const double d )
59{ n[VX] *= d; n[VY] *= d; return *this; }
60
61vec2& vec2::operator /= ( const double d )
62{ double d_inv = 1./d; n[VX] *= d_inv; n[VY] *= d_inv; return *this; }
63
64double& vec2::operator [] ( int i) {
65 if (i < VX || i > VY)
66 V_ERROR("vec2 [] operator: illegal access; index = " << i << '\n')
67 return n[i];
68}
69
70const double& vec2::operator [] ( int i) const {
71 if (i < VX || i > VY)
72 V_ERROR("vec2 [] operator: illegal access; index = " << i << '\n')
73 return n[i];
74}
75
76
77// SPECIAL FUNCTIONS
78
79double vec2::length()
80{ return sqrt(length2()); }
81
82double vec2::length2()
83{ return n[VX]*n[VX] + n[VY]*n[VY]; }
84
85vec2& vec2::normalize() // it is up to caller to avoid divide-by-zero
86{ *this /= length(); return *this; }
87
88vec2& vec2::apply(V_FCT_PTR fct)
89{ n[VX] = (*fct)(n[VX]); n[VY] = (*fct)(n[VY]); return *this; }
90
91
92// FRIENDS
93
94namespace sc {
95
96vec2 operator - (const vec2& a)
97{ return vec2(-a.n[VX],-a.n[VY]); }
98
99vec2 operator + (const vec2& a, const vec2& b)
100{ return vec2(a.n[VX]+ b.n[VX], a.n[VY] + b.n[VY]); }
101
102vec2 operator - (const vec2& a, const vec2& b)
103{ return vec2(a.n[VX]-b.n[VX], a.n[VY]-b.n[VY]); }
104
105vec2 operator * (const vec2& a, const double d)
106{ return vec2(d*a.n[VX], d*a.n[VY]); }
107
108vec2 operator * (const double d, const vec2& a)
109{ return a*d; }
110
111vec2 operator * (const mat3& a, const vec2& v) {
112 vec3 av;
113
114 av.n[VX] = a.v[0].n[VX]*v.n[VX] + a.v[0].n[VY]*v.n[VY] + a.v[0].n[VZ];
115 av.n[VY] = a.v[1].n[VX]*v.n[VX] + a.v[1].n[VY]*v.n[VY] + a.v[1].n[VZ];
116 av.n[VZ] = a.v[2].n[VX]*v.n[VX] + a.v[2].n[VY]*v.n[VY] + a.v[2].n[VZ];
117 return av;
118}
119
120vec2 operator * (const vec2& v, const mat3& a)
121{ return a.transpose() * v; }
122
123double operator * (const vec2& a, const vec2& b)
124{ return (a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY]); }
125
126vec2 operator / (const vec2& a, const double d)
127{ double d_inv = 1./d; return vec2(a.n[VX]*d_inv, a.n[VY]*d_inv); }
128
129vec3 operator ^ (const vec2& a, const vec2& b)
130{ return vec3(0.0, 0.0, a.n[VX] * b.n[VY] - b.n[VX] * a.n[VY]); }
131
132int operator == (const vec2& a, const vec2& b)
133{ return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]); }
134
135int operator != (const vec2& a, const vec2& b)
136{ return !(a == b); }
137
138ostream& operator << (ostream& s, vec2& v)
139{ return s << "| " << v.n[VX] << ' ' << v.n[VY] << " |"; }
140
141istream& operator >> (istream& s, vec2& v) {
142 vec2 v_tmp;
143 char c = ' ';
144
145 while (isspace(c))
146 s >> c;
147 // The vectors can be formatted either as x y or | x y |
148 if (c == '|') {
149 s >> v_tmp[VX] >> v_tmp[VY];
150 while (s >> c && isspace(c)) ;
151 //if (c != '|')
152 // s.set(_bad);
153 }
154 else {
155 s.putback(c);
156 s >> v_tmp[VX] >> v_tmp[VY];
157 }
158 if (s)
159 v = v_tmp;
160 return s;
161}
162
163void swap(vec2& a, vec2& b)
164{ vec2 tmp(a); a = b; b = tmp; }
165
166vec2 min(const vec2& a, const vec2& b)
167{ return vec2(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY])); }
168
169vec2 max(const vec2& a, const vec2& b)
170{ return vec2(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY])); }
171
172vec2 prod(const vec2& a, const vec2& b)
173{ return vec2(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY]); }
174
175}
176
177/****************************************************************
178* *
179* vec3 Member functions *
180* *
181****************************************************************/
182
183// CONSTRUCTORS
184
185vec3::vec3() {}
186
187vec3::vec3(const double x, const double y, const double z)
188{ n[VX] = x; n[VY] = y; n[VZ] = z; }
189
190vec3::vec3(const double d)
191{ n[VX] = n[VY] = n[VZ] = d; }
192
193vec3::vec3(const vec3& v)
194{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; }
195
196vec3::vec3(const vec2& v)
197{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = 1.0; }
198
199vec3::vec3(const vec2& v, double d)
200{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = d; }
201
202vec3::vec3(const vec4& v) // it is up to caller to avoid divide-by-zero
203{ n[VX] = v.n[VX] / v.n[VW]; n[VY] = v.n[VY] / v.n[VW];
204 n[VZ] = v.n[VZ] / v.n[VW]; }
205
206vec3::vec3(const vec4& v, int dropAxis) {
207 switch (dropAxis) {
208 case VX: n[VX] = v.n[VY]; n[VY] = v.n[VZ]; n[VZ] = v.n[VW]; break;
209 case VY: n[VX] = v.n[VX]; n[VY] = v.n[VZ]; n[VZ] = v.n[VW]; break;
210 case VZ: n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VW]; break;
211 default: n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; break;
212 }
213}
214
215
216// ASSIGNMENT OPERATORS
217
218vec3& vec3::operator = (const vec3& v)
219{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; return *this; }
220
221vec3& vec3::operator += ( const vec3& v )
222{ n[VX] += v.n[VX]; n[VY] += v.n[VY]; n[VZ] += v.n[VZ]; return *this; }
223
224vec3& vec3::operator -= ( const vec3& v )
225{ n[VX] -= v.n[VX]; n[VY] -= v.n[VY]; n[VZ] -= v.n[VZ]; return *this; }
226
227vec3& vec3::operator *= ( const double d )
228{ n[VX] *= d; n[VY] *= d; n[VZ] *= d; return *this; }
229
230vec3& vec3::operator /= ( const double d )
231{ double d_inv = 1./d; n[VX] *= d_inv; n[VY] *= d_inv; n[VZ] *= d_inv;
232 return *this; }
233
234double& vec3::operator [] ( int i) {
235 if (i < VX || i > VZ)
236 V_ERROR("vec3 [] operator: illegal access; index = " << i << '\n')
237 return n[i];
238}
239
240const double& vec3::operator [] ( int i) const {
241 if (i < VX || i > VZ)
242 V_ERROR("vec3 [] operator: illegal access; index = " << i << '\n')
243 return n[i];
244}
245
246
247// SPECIAL FUNCTIONS
248
249double vec3::length()
250{ return sqrt(length2()); }
251
252double vec3::length2()
253{ return n[VX]*n[VX] + n[VY]*n[VY] + n[VZ]*n[VZ]; }
254
255vec3& vec3::normalize() // it is up to caller to avoid divide-by-zero
256{ *this /= length(); return *this; }
257
258vec3& vec3::apply(V_FCT_PTR fct)
259{ n[VX] = (*fct)(n[VX]); n[VY] = (*fct)(n[VY]); n[VZ] = (*fct)(n[VZ]);
260return *this; }
261
262
263// FRIENDS
264
265namespace sc {
266
267vec3 operator - (const vec3& a)
268{ return vec3(-a.n[VX],-a.n[VY],-a.n[VZ]); }
269
270vec3 operator + (const vec3& a, const vec3& b)
271{ return vec3(a.n[VX]+ b.n[VX], a.n[VY] + b.n[VY], a.n[VZ] + b.n[VZ]); }
272
273vec3 operator - (const vec3& a, const vec3& b)
274{ return vec3(a.n[VX]-b.n[VX], a.n[VY]-b.n[VY], a.n[VZ]-b.n[VZ]); }
275
276vec3 operator * (const vec3& a, const double d)
277{ return vec3(d*a.n[VX], d*a.n[VY], d*a.n[VZ]); }
278
279vec3 operator * (const double d, const vec3& a)
280{ return a*d; }
281
282vec3 operator * (const mat4& a, const vec3& v)
283{ return a * vec4(v); }
284
285vec3 operator * (const vec3& v, const mat4& a)
286{ return a.transpose() * v; }
287
288double operator * (const vec3& a, const vec3& b)
289{ return (a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY] + a.n[VZ]*b.n[VZ]); }
290
291vec3 operator / (const vec3& a, const double d)
292{ double d_inv = 1./d; return vec3(a.n[VX]*d_inv, a.n[VY]*d_inv,
293 a.n[VZ]*d_inv); }
294
295vec3 operator ^ (const vec3& a, const vec3& b) {
296 return vec3(a.n[VY]*b.n[VZ] - a.n[VZ]*b.n[VY],
297 a.n[VZ]*b.n[VX] - a.n[VX]*b.n[VZ],
298 a.n[VX]*b.n[VY] - a.n[VY]*b.n[VX]);
299}
300
301int operator == (const vec3& a, const vec3& b)
302{ return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]) && (a.n[VZ] == b.n[VZ]);
303}
304
305int operator != (const vec3& a, const vec3& b)
306{ return !(a == b); }
307
308ostream& operator << (ostream& s, vec3& v)
309{ return s << "| " << v.n[VX] << ' ' << v.n[VY] << ' ' << v.n[VZ] << " |"; }
310
311istream& operator >> (istream& s, vec3& v) {
312 vec3 v_tmp;
313 char c = ' ';
314
315 while (isspace(c))
316 s >> c;
317 // The vectors can be formatted either as x y z or | x y z |
318 if (c == '|') {
319 s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ];
320 while (s >> c && isspace(c)) ;
321 //if (c != '|')
322 // s.set(_bad);
323 }
324 else {
325 s.putback(c);
326 s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ];
327 }
328 if (s)
329 v = v_tmp;
330 return s;
331}
332
333void swap(vec3& a, vec3& b)
334{ vec3 tmp(a); a = b; b = tmp; }
335
336vec3 min(const vec3& a, const vec3& b)
337{ return vec3(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY]), MIN(a.n[VZ],
338 b.n[VZ])); }
339
340vec3 max(const vec3& a, const vec3& b)
341{ return vec3(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY]), MAX(a.n[VZ],
342 b.n[VZ])); }
343
344vec3 prod(const vec3& a, const vec3& b)
345{ return vec3(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY], a.n[VZ] * b.n[VZ]); }
346
347}
348
349/****************************************************************
350* *
351* vec4 Member functions *
352* *
353****************************************************************/
354
355// CONSTRUCTORS
356
357vec4::vec4() {}
358
359vec4::vec4(const double x, const double y, const double z, const double w)
360{ n[VX] = x; n[VY] = y; n[VZ] = z; n[VW] = w; }
361
362vec4::vec4(const double d)
363{ n[VX] = n[VY] = n[VZ] = n[VW] = d; }
364
365vec4::vec4(const vec4& v)
366{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = v.n[VW]; }
367
368vec4::vec4(const vec3& v)
369{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = 1.0; }
370
371vec4::vec4(const vec3& v, const double d)
372{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = d; }
373
374
375// ASSIGNMENT OPERATORS
376
377vec4& vec4::operator = (const vec4& v)
378{ n[VX] = v.n[VX]; n[VY] = v.n[VY]; n[VZ] = v.n[VZ]; n[VW] = v.n[VW];
379return *this; }
380
381vec4& vec4::operator += ( const vec4& v )
382{ n[VX] += v.n[VX]; n[VY] += v.n[VY]; n[VZ] += v.n[VZ]; n[VW] += v.n[VW];
383return *this; }
384
385vec4& vec4::operator -= ( const vec4& v )
386{ n[VX] -= v.n[VX]; n[VY] -= v.n[VY]; n[VZ] -= v.n[VZ]; n[VW] -= v.n[VW];
387return *this; }
388
389vec4& vec4::operator *= ( const double d )
390{ n[VX] *= d; n[VY] *= d; n[VZ] *= d; n[VW] *= d; return *this; }
391
392vec4& vec4::operator /= ( const double d )
393{ double d_inv = 1./d; n[VX] *= d_inv; n[VY] *= d_inv; n[VZ] *= d_inv;
394 n[VW] *= d_inv; return *this; }
395
396double& vec4::operator [] ( int i) {
397 if (i < VX || i > VW)
398 V_ERROR("vec4 [] operator: illegal access; index = " << i << '\n')
399 return n[i];
400}
401
402const double& vec4::operator [] ( int i) const {
403 if (i < VX || i > VW)
404 V_ERROR("vec4 [] operator: illegal access; index = " << i << '\n')
405 return n[i];
406}
407
408
409// SPECIAL FUNCTIONS
410
411double vec4::length()
412{ return sqrt(length2()); }
413
414double vec4::length2()
415{ return n[VX]*n[VX] + n[VY]*n[VY] + n[VZ]*n[VZ] + n[VW]*n[VW]; }
416
417vec4& vec4::normalize() // it is up to caller to avoid divide-by-zero
418{ *this /= length(); return *this; }
419
420vec4& vec4::apply(V_FCT_PTR fct)
421{ n[VX] = (*fct)(n[VX]); n[VY] = (*fct)(n[VY]); n[VZ] = (*fct)(n[VZ]);
422n[VW] = (*fct)(n[VW]); return *this; }
423
424
425// FRIENDS
426
427namespace sc {
428
429vec4 operator - (const vec4& a)
430{ return vec4(-a.n[VX],-a.n[VY],-a.n[VZ],-a.n[VW]); }
431
432vec4 operator + (const vec4& a, const vec4& b)
433{ return vec4(a.n[VX] + b.n[VX], a.n[VY] + b.n[VY], a.n[VZ] + b.n[VZ],
434 a.n[VW] + b.n[VW]); }
435
436vec4 operator - (const vec4& a, const vec4& b)
437{ return vec4(a.n[VX] - b.n[VX], a.n[VY] - b.n[VY], a.n[VZ] - b.n[VZ],
438 a.n[VW] - b.n[VW]); }
439
440vec4 operator * (const vec4& a, const double d)
441{ return vec4(d*a.n[VX], d*a.n[VY], d*a.n[VZ], d*a.n[VW] ); }
442
443vec4 operator * (const double d, const vec4& a)
444{ return a*d; }
445
446vec4 operator * (const mat4& a, const vec4& v) {
447 #define ROWCOL(i) a.v[i].n[0]*v.n[VX] + a.v[i].n[1]*v.n[VY] \
448 + a.v[i].n[2]*v.n[VZ] + a.v[i].n[3]*v.n[VW]
449 return vec4(ROWCOL(0), ROWCOL(1), ROWCOL(2), ROWCOL(3));
450 #undef ROWCOL
451}
452
453vec4 operator * (const vec4& v, const mat4& a)
454{ return a.transpose() * v; }
455
456double operator * (const vec4& a, const vec4& b)
457{ return (a.n[VX]*b.n[VX] + a.n[VY]*b.n[VY] + a.n[VZ]*b.n[VZ] +
458 a.n[VW]*b.n[VW]); }
459
460vec4 operator / (const vec4& a, const double d)
461{ double d_inv = 1./d; return vec4(a.n[VX]*d_inv, a.n[VY]*d_inv, a.n[VZ]*d_inv,
462 a.n[VW]*d_inv); }
463
464int operator == (const vec4& a, const vec4& b)
465{ return (a.n[VX] == b.n[VX]) && (a.n[VY] == b.n[VY]) && (a.n[VZ] == b.n[VZ])
466 && (a.n[VW] == b.n[VW]); }
467
468int operator != (const vec4& a, const vec4& b)
469{ return !(a == b); }
470
471ostream& operator << (ostream& s, vec4& v)
472{ return s << "| " << v.n[VX] << ' ' << v.n[VY] << ' ' << v.n[VZ] << ' '
473 << v.n[VW] << " |"; }
474
475istream& operator >> (istream& s, vec4& v) {
476 vec4 v_tmp;
477 char c = ' ';
478
479 while (isspace(c))
480 s >> c;
481 // The vectors can be formatted either as x y z w or | x y z w |
482 if (c == '|') {
483 s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ] >> v_tmp[VW];
484 while (s >> c && isspace(c)) ;
485 //if (c != '|')
486 // s.set(_bad);
487 }
488 else {
489 s.putback(c);
490 s >> v_tmp[VX] >> v_tmp[VY] >> v_tmp[VZ] >> v_tmp[VW];
491 }
492 if (s)
493 v = v_tmp;
494 return s;
495}
496
497void swap(vec4& a, vec4& b)
498{ vec4 tmp(a); a = b; b = tmp; }
499
500vec4 min(const vec4& a, const vec4& b)
501{ return vec4(MIN(a.n[VX], b.n[VX]), MIN(a.n[VY], b.n[VY]), MIN(a.n[VZ],
502 b.n[VZ]), MIN(a.n[VW], b.n[VW])); }
503
504vec4 max(const vec4& a, const vec4& b)
505{ return vec4(MAX(a.n[VX], b.n[VX]), MAX(a.n[VY], b.n[VY]), MAX(a.n[VZ],
506 b.n[VZ]), MAX(a.n[VW], b.n[VW])); }
507
508vec4 prod(const vec4& a, const vec4& b)
509{ return vec4(a.n[VX] * b.n[VX], a.n[VY] * b.n[VY], a.n[VZ] * b.n[VZ],
510 a.n[VW] * b.n[VW]); }
511
512}
513
514/****************************************************************
515* *
516* mat3 member functions *
517* *
518****************************************************************/
519
520// CONSTRUCTORS
521
522mat3::mat3() {}
523
524mat3::mat3(const vec3& v0, const vec3& v1, const vec3& v2)
525{ v[0] = v0; v[1] = v1; v[2] = v2; }
526
527mat3::mat3(const double d)
528{ v[0] = v[1] = v[2] = vec3(d); }
529
530mat3::mat3(const mat3& m)
531{ v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; }
532
533
534// ASSIGNMENT OPERATORS
535
536mat3& mat3::operator = ( const mat3& m )
537{ v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; return *this; }
538
539mat3& mat3::operator += ( const mat3& m )
540{ v[0] += m.v[0]; v[1] += m.v[1]; v[2] += m.v[2]; return *this; }
541
542mat3& mat3::operator -= ( const mat3& m )
543{ v[0] -= m.v[0]; v[1] -= m.v[1]; v[2] -= m.v[2]; return *this; }
544
545mat3& mat3::operator *= ( const double d )
546{ v[0] *= d; v[1] *= d; v[2] *= d; return *this; }
547
548mat3& mat3::operator /= ( const double d )
549{ v[0] /= d; v[1] /= d; v[2] /= d; return *this; }
550
551vec3& mat3::operator [] ( int i) {
552 if (i < VX || i > VZ)
553 V_ERROR("mat3 [] operator: illegal access; index = " << i << '\n')
554 return v[i];
555}
556
557const vec3& mat3::operator [] ( int i) const {
558 if (i < VX || i > VZ)
559 V_ERROR("mat3 [] operator: illegal access; index = " << i << '\n')
560 return v[i];
561}
562
563
564// SPECIAL FUNCTIONS
565
566mat3 mat3::transpose() const {
567 return mat3(vec3(v[0][0], v[1][0], v[2][0]),
568 vec3(v[0][1], v[1][1], v[2][1]),
569 vec3(v[0][2], v[1][2], v[2][2]));
570}
571
572mat3 mat3::inverse() // Gauss-Jordan elimination with partial pivoting
573 {
574 mat3 a(*this), // As a evolves from original mat into identity
575 b(identity2D()); // b evolves from identity into inverse(a)
576 int i, j, i1;
577
578 // Loop over cols of a from left to right, eliminating above and below diag
579 for (j=0; j<3; j++) { // Find largest pivot in column j among rows j..2
580 i1 = j; // Row with largest pivot candidate
581 for (i=j+1; i<3; i++)
582 if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j]))
583 i1 = i;
584
585 // Swap rows i1 and j in a and b to put pivot on diagonal
586 swap(a.v[i1], a.v[j]);
587 swap(b.v[i1], b.v[j]);
588
589 // Scale row j to have a unit diagonal
590 if (a.v[j].n[j]==0.)
591 V_ERROR("mat3::inverse: singular matrix; can't invert\n")
592 b.v[j] /= a.v[j].n[j];
593 a.v[j] /= a.v[j].n[j];
594
595 // Eliminate off-diagonal elems in col j of a, doing identical ops to b
596 for (i=0; i<3; i++)
597 if (i!=j) {
598 b.v[i] -= a.v[i].n[j]*b.v[j];
599 a.v[i] -= a.v[i].n[j]*a.v[j];
600 }
601 }
602 return b;
603}
604
605mat3& mat3::apply(V_FCT_PTR fct) {
606 v[VX].apply(fct);
607 v[VY].apply(fct);
608 v[VZ].apply(fct);
609 return *this;
610}
611
612
613// FRIENDS
614
615namespace sc {
616
617mat3 operator - (const mat3& a)
618{ return mat3(-a.v[0], -a.v[1], -a.v[2]); }
619
620mat3 operator + (const mat3& a, const mat3& b)
621{ return mat3(a.v[0] + b.v[0], a.v[1] + b.v[1], a.v[2] + b.v[2]); }
622
623mat3 operator - (const mat3& a, const mat3& b)
624{ return mat3(a.v[0] - b.v[0], a.v[1] - b.v[1], a.v[2] - b.v[2]); }
625
626mat3 operator * (const mat3& a, const mat3& b) {
627 #define ROWCOL(i, j) \
628 a.v[i].n[0]*b.v[0][j] + a.v[i].n[1]*b.v[1][j] + a.v[i].n[2]*b.v[2][j]
629 return mat3(vec3(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2)),
630 vec3(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2)),
631 vec3(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2)));
632 #undef ROWCOL
633}
634
635mat3 operator * (const mat3& a, const double d)
636{ return mat3(a.v[0] * d, a.v[1] * d, a.v[2] * d); }
637
638mat3 operator * (const double d, const mat3& a)
639{ return a*d; }
640
641mat3 operator / (const mat3& a, const double d)
642{ return mat3(a.v[0] / d, a.v[1] / d, a.v[2] / d); }
643
644int operator == (const mat3& a, const mat3& b)
645{ return (a.v[0] == b.v[0]) && (a.v[1] == b.v[1]) && (a.v[2] == b.v[2]); }
646
647int operator != (const mat3& a, const mat3& b)
648{ return !(a == b); }
649
650ostream& operator << (ostream& s, mat3& m)
651{ return s << m.v[VX] << '\n' << m.v[VY] << '\n' << m.v[VZ]; }
652
653istream& operator >> (istream& s, mat3& m) {
654 mat3 m_tmp;
655
656 s >> m_tmp[VX] >> m_tmp[VY] >> m_tmp[VZ];
657 if (s)
658 m = m_tmp;
659 return s;
660}
661
662void swap(mat3& a, mat3& b)
663{ mat3 tmp(a); a = b; b = tmp; }
664
665}
666
667/****************************************************************
668* *
669* mat4 member functions *
670* *
671****************************************************************/
672
673// CONSTRUCTORS
674
675mat4::mat4() {}
676
677mat4::mat4(const vec4& v0, const vec4& v1, const vec4& v2, const vec4& v3)
678{ v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; }
679
680mat4::mat4(const double d)
681{ v[0] = v[1] = v[2] = v[3] = vec4(d); }
682
683mat4::mat4(const mat4& m)
684{ v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; v[3] = m.v[3]; }
685
686
687// ASSIGNMENT OPERATORS
688
689mat4& mat4::operator = ( const mat4& m )
690{ v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; v[3] = m.v[3];
691return *this; }
692
693mat4& mat4::operator += ( const mat4& m )
694{ v[0] += m.v[0]; v[1] += m.v[1]; v[2] += m.v[2]; v[3] += m.v[3];
695return *this; }
696
697mat4& mat4::operator -= ( const mat4& m )
698{ v[0] -= m.v[0]; v[1] -= m.v[1]; v[2] -= m.v[2]; v[3] -= m.v[3];
699return *this; }
700
701mat4& mat4::operator *= ( const double d )
702{ v[0] *= d; v[1] *= d; v[2] *= d; v[3] *= d; return *this; }
703
704mat4& mat4::operator /= ( const double d )
705{ v[0] /= d; v[1] /= d; v[2] /= d; v[3] /= d; return *this; }
706
707vec4& mat4::operator [] ( int i) {
708 if (i < VX || i > VW)
709 V_ERROR("mat4 [] operator: illegal access; index = " << i << '\n')
710 return v[i];
711}
712
713const vec4& mat4::operator [] ( int i) const {
714 if (i < VX || i > VW)
715 V_ERROR("mat4 [] operator: illegal access; index = " << i << '\n')
716 return v[i];
717}
718
719// SPECIAL FUNCTIONS;
720
721mat4 mat4::transpose() const {
722 return mat4(vec4(v[0][0], v[1][0], v[2][0], v[3][0]),
723 vec4(v[0][1], v[1][1], v[2][1], v[3][1]),
724 vec4(v[0][2], v[1][2], v[2][2], v[3][2]),
725 vec4(v[0][3], v[1][3], v[2][3], v[3][3]));
726}
727
728mat4 mat4::inverse() // Gauss-Jordan elimination with partial pivoting
729{
730 mat4 a(*this), // As a evolves from original mat into identity
731 b(identity3D()); // b evolves from identity into inverse(a)
732 int i, j, i1;
733
734 // Loop over cols of a from left to right, eliminating above and below diag
735 for (j=0; j<4; j++) { // Find largest pivot in column j among rows j..3
736 i1 = j; // Row with largest pivot candidate
737 for (i=j+1; i<4; i++)
738 if (fabs(a.v[i].n[j]) > fabs(a.v[i1].n[j]))
739 i1 = i;
740
741 // Swap rows i1 and j in a and b to put pivot on diagonal
742 swap(a.v[i1], a.v[j]);
743 swap(b.v[i1], b.v[j]);
744
745 // Scale row j to have a unit diagonal
746 if (a.v[j].n[j]==0.)
747 V_ERROR("mat4::inverse: singular matrix; can't invert\n");
748 b.v[j] /= a.v[j].n[j];
749 a.v[j] /= a.v[j].n[j];
750
751 // Eliminate off-diagonal elems in col j of a, doing identical ops to b
752 for (i=0; i<4; i++)
753 if (i!=j) {
754 b.v[i] -= a.v[i].n[j]*b.v[j];
755 a.v[i] -= a.v[i].n[j]*a.v[j];
756 }
757 }
758 return b;
759}
760
761mat4& mat4::apply(V_FCT_PTR fct)
762{ v[VX].apply(fct); v[VY].apply(fct); v[VZ].apply(fct); v[VW].apply(fct);
763return *this; }
764
765
766// FRIENDS
767
768namespace sc {
769
770mat4 operator - (const mat4& a)
771{ return mat4(-a.v[0], -a.v[1], -a.v[2], -a.v[3]); }
772
773mat4 operator + (const mat4& a, const mat4& b)
774{ return mat4(a.v[0] + b.v[0], a.v[1] + b.v[1], a.v[2] + b.v[2],
775 a.v[3] + b.v[3]);
776}
777
778mat4 operator - (const mat4& a, const mat4& b)
779{ return mat4(a.v[0] - b.v[0], a.v[1] - b.v[1], a.v[2] - b.v[2], a.v[3] - b.v[3]); }
780
781mat4 operator * (const mat4& a, const mat4& b) {
782 #define ROWCOL(i, j) a.v[i].n[0]*b.v[0][j] + a.v[i].n[1]*b.v[1][j] + \
783 a.v[i].n[2]*b.v[2][j] + a.v[i].n[3]*b.v[3][j]
784 return mat4(
785 vec4(ROWCOL(0,0), ROWCOL(0,1), ROWCOL(0,2), ROWCOL(0,3)),
786 vec4(ROWCOL(1,0), ROWCOL(1,1), ROWCOL(1,2), ROWCOL(1,3)),
787 vec4(ROWCOL(2,0), ROWCOL(2,1), ROWCOL(2,2), ROWCOL(2,3)),
788 vec4(ROWCOL(3,0), ROWCOL(3,1), ROWCOL(3,2), ROWCOL(3,3))
789 );
790}
791
792mat4 operator * (const mat4& a, const double d)
793{ return mat4(a.v[0] * d, a.v[1] * d, a.v[2] * d, a.v[3] * d); }
794
795mat4 operator * (const double d, const mat4& a)
796{ return a*d; }
797
798mat4 operator / (const mat4& a, const double d)
799{ return mat4(a.v[0] / d, a.v[1] / d, a.v[2] / d, a.v[3] / d); }
800
801int operator == (const mat4& a, const mat4& b)
802{ return ((a.v[0] == b.v[0]) && (a.v[1] == b.v[1]) && (a.v[2] == b.v[2]) &&
803 (a.v[3] == b.v[3])); }
804
805int operator != (const mat4& a, const mat4& b)
806{ return !(a == b); }
807
808ostream& operator << (ostream& s, mat4& m)
809{ return s << m.v[VX] << '\n' << m.v[VY] << '\n' << m.v[VZ] << '\n' << m.v[VW]; }
810
811istream& operator >> (istream& s, mat4& m)
812{
813 mat4 m_tmp;
814
815 s >> m_tmp[VX] >> m_tmp[VY] >> m_tmp[VZ] >> m_tmp[VW];
816 if (s)
817 m = m_tmp;
818 return s;
819}
820
821void swap(mat4& a, mat4& b)
822{ mat4 tmp(a); a = b; b = tmp; }
823
824}
825
826
827/****************************************************************
828* *
829* 2D functions and 3D functions *
830* *
831****************************************************************/
832
833namespace sc {
834
835mat3 identity2D()
836{ return mat3(vec3(1.0, 0.0, 0.0),
837 vec3(0.0, 1.0, 0.0),
838 vec3(0.0, 0.0, 1.0)); }
839
840mat3 translation2D(const vec2& v)
841{ return mat3(vec3(1.0, 0.0, v[VX]),
842 vec3(0.0, 1.0, v[VY]),
843 vec3(0.0, 0.0, 1.0)); }
844
845mat3 rotation2D(const vec2& Center, const double angleDeg) {
846 double angleRad = angleDeg * M_PI / 180.0,
847 c = cos(angleRad),
848 s = sin(angleRad);
849
850 return mat3(vec3(c, -s, Center[VX] * (1.0-c) + Center[VY] * s),
851 vec3(s, c, Center[VY] * (1.0-c) - Center[VX] * s),
852 vec3(0.0, 0.0, 1.0));
853}
854
855mat3 scaling2D(const vec2& scaleVector)
856{ return mat3(vec3(scaleVector[VX], 0.0, 0.0),
857 vec3(0.0, scaleVector[VY], 0.0),
858 vec3(0.0, 0.0, 1.0)); }
859
860mat4 identity3D()
861{ return mat4(vec4(1.0, 0.0, 0.0, 0.0),
862 vec4(0.0, 1.0, 0.0, 0.0),
863 vec4(0.0, 0.0, 1.0, 0.0),
864 vec4(0.0, 0.0, 0.0, 1.0)); }
865
866mat4 translation3D(const vec3& v)
867{ return mat4(vec4(1.0, 0.0, 0.0, v[VX]),
868 vec4(0.0, 1.0, 0.0, v[VY]),
869 vec4(0.0, 0.0, 1.0, v[VZ]),
870 vec4(0.0, 0.0, 0.0, 1.0)); }
871
872mat4 rotation3D(const vec3& Axisarg, const double angleDeg) {
873 double angleRad = angleDeg * M_PI / 180.0,
874 c = cos(angleRad),
875 s = sin(angleRad),
876 t = 1.0 - c;
877
878 vec3 Axis(Axisarg);
879 Axis.normalize();
880 return mat4(vec4(t * Axis[VX] * Axis[VX] + c,
881 t * Axis[VX] * Axis[VY] - s * Axis[VZ],
882 t * Axis[VX] * Axis[VZ] + s * Axis[VY],
883 0.0),
884 vec4(t * Axis[VX] * Axis[VY] + s * Axis[VZ],
885 t * Axis[VY] * Axis[VY] + c,
886 t * Axis[VY] * Axis[VZ] - s * Axis[VX],
887 0.0),
888 vec4(t * Axis[VX] * Axis[VZ] - s * Axis[VY],
889 t * Axis[VY] * Axis[VZ] + s * Axis[VX],
890 t * Axis[VZ] * Axis[VZ] + c,
891 0.0),
892 vec4(0.0, 0.0, 0.0, 1.0));
893}
894
895mat4 scaling3D(const vec3& scaleVector)
896{ return mat4(vec4(scaleVector[VX], 0.0, 0.0, 0.0),
897 vec4(0.0, scaleVector[VY], 0.0, 0.0),
898 vec4(0.0, 0.0, scaleVector[VZ], 0.0),
899 vec4(0.0, 0.0, 0.0, 1.0)); }
900
901mat4 perspective3D(const double d)
902{ return mat4(vec4(1.0, 0.0, 0.0, 0.0),
903 vec4(0.0, 1.0, 0.0, 0.0),
904 vec4(0.0, 0.0, 1.0, 0.0),
905 vec4(0.0, 0.0, 1.0/d, 0.0)); }
906
907}
Note: See TracBrowser for help on using the repository browser.