RayZaler 0.1
The free opto-mechanical simulation framework
Matrix.h
1//
2// Copyright (c) 2024 Gonzalo José Carracedo Carballal
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU Lesser General Public License as
6// published by the Free Software Foundation, either version 3 of the
7// License, or (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful, but
10// WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU Lesser General Public License for more details.
13//
14// You should have received a copy of the GNU Lesser General Public
15// License along with this program. If not, see
16// <http://www.gnu.org/licenses/>
17//
18
19#ifndef _MATRIX_H
20#define _MATRIX_H
21
22#include "Vector.h"
23#include <iostream>
24
25namespace RZ {
26 // 3-D matrices are actually a bunch of 3 Vec3
27
28 static inline Real
29 deg2rad(Real deg)
30 {
31 Real rad = deg / 180. * M_PI;
32 rad -= 2. * M_PI * std::floor((rad + M_PI) * (0.5 / M_PI));
33 return rad;
34 }
35
36 static inline Real
37 rad2deg(Real rad)
38 {
39 Real deg = rad / M_PI * 180.;
40 deg -= 360. * std::floor((deg + 180.) * (1. / 360.));
41 return deg;
42 }
43
44 struct Matrix3;
45
46 static inline RZ::Matrix3 operator *(RZ::Real k, RZ::Matrix3 M);
47
48 struct Matrix3 {
49 union {
50 Vec3 rows[3];
51 struct {
52 Vec3 vx, vy, vz;
53 } row;
54
55 Real coef[3][3];
56 };
57
58 Matrix3() : Matrix3(Vec3::eX(), Vec3::eY(), Vec3::eZ()) {}
59
60 Matrix3(Vec3 const &row1, Vec3 const &row2, Vec3 const &row3)
61 {
62 row.vx = row1;
63 row.vy = row2;
64 row.vz = row3;
65 }
66
67 Matrix3(const RZ::Real coef[3][3])
68 {
69 memcpy(this->coef, coef, 3 * 3 * sizeof (RZ::Real));
70 }
71
72 inline Vec3 const &
73 vx() const
74 {
75 return row.vx;
76 }
77
78 inline Vec3 const &
79 vy() const
80 {
81 return row.vy;
82 }
83
84 inline Vec3 const &
85 vz() const
86 {
87 return row.vz;
88 }
89
90 // In-place apply (left)
91 inline void
92 applyLeft(Matrix3 const &m)
93 {
94 *this = m * *this;
95 }
96
97 // In-place apply (right)
98 inline void
99 applyRight(Matrix3 const &m)
100 {
101 *this = *this * m;
102 }
103
104 // Matrix-vector product
105 inline Vec3
106 operator *(Vec3 const &v) const
107 {
108 return Vec3(row.vx * v, row.vy * v, row.vz * v);
109 }
110
111 // Matrix-matrix product
112 inline Matrix3
113 operator *(Matrix3 const &m) const
114 {
115 Vec3 cols[] = {
116 Vec3(m.row.vx.x, m.row.vy.x, m.row.vz.x),
117 Vec3(m.row.vx.y, m.row.vy.y, m.row.vz.y),
118 Vec3(m.row.vx.z, m.row.vy.z, m.row.vz.z)
119 };
120
121 return Matrix3(
122 Vec3(row.vx * cols[0], row.vx * cols[1], row.vx * cols[2]),
123 Vec3(row.vy * cols[0], row.vy * cols[1], row.vy * cols[2]),
124 Vec3(row.vz * cols[0], row.vz * cols[1], row.vz * cols[2])
125 );
126 }
127
128 // Matrix-scalar product
129 inline Matrix3
130 operator *(Real k) const
131 {
132 return Matrix3(k * row.vx, k * row.vy, k * row.vz);
133 }
134
135 // Matrix-scalar division
136 inline Matrix3
137 operator /(Real k) const
138 {
139 return *this * (1. / k);
140 }
141
142 // Matrix addition
143 inline Matrix3
144 operator +(Matrix3 const &m)
145 {
146 return Matrix3(row.vx + m.row.vx, row.vy + m.row.vy, row.vz + m.row.vz);
147 }
148
149 // Matrix subtraction
150 inline Matrix3
151 operator -(Matrix3 const &m)
152 {
153 return Matrix3(row.vx - m.row.vx, row.vy - m.row.vy, row.vz - m.row.vz);
154 }
155
156 // Determinant
157 inline Real
158 det() const
159 {
160 return
161 row.vx.x * row.vy.y * row.vz.z + row.vx.y * row.vy.z * row.vz.x + row.vx.z * row.vy.x * row.vz.y
162 - (row.vx.x * row.vy.z * row.vz.y + row.vx.y * row.vy.x * row.vz.z + row.vx.z * row.vy.y * row.vz.x);
163 }
164
165 // Trace
166 inline Real
167 tr() const
168 {
169 return coef[0][0] + coef[1][1] + coef[2][2];
170 }
171
172 // Transpose
173 inline Matrix3
174 t() const
175 {
176 return Matrix3(
177 Vec3(row.vx.x, row.vy.x, row.vz.x),
178 Vec3(row.vx.y, row.vy.y, row.vz.y),
179 Vec3(row.vx.z, row.vy.z, row.vz.z)
180 );
181 }
182
183 // Common matrices
184 static inline Matrix3
185 zero()
186 {
187 return Matrix3(Vec3::zero(), Vec3::zero(), Vec3::zero());
188 }
189
190 static inline Matrix3
191 eye()
192 {
193 return Matrix3(Vec3::eX(), Vec3::eY(), Vec3::eZ());
194 }
195
196 static inline Matrix3
197 crossMatrix(Vec3 const &k)
198 {
199 return Matrix3(
200 Vec3(0, -k.z, +k.y),
201 Vec3(+k.z, 0, -k.x),
202 Vec3(-k.y, +k.x, 0)
203 );
204 }
205
206 static inline Matrix3
207 rot(Vec3 const &k, Real theta)
208 {
209 Matrix3 K = crossMatrix(k);
210 return eye() + K * sin(theta) + (1 - cos(theta)) * K * K;
211 }
212
213 //
214 // The AzEl orientation matrix works as follows:
215 // X points towards the North
216 // Y points towards the West
217 // Z points towards the Zenith
218 //
219
220 static inline Matrix3
221 azel(Real az, Real el)
222 {
223 return Matrix3::rot(Vec3::eY(), M_PI / 2 - el) * Matrix3::rot(Vec3::eZ(), -az);
224 }
225
226 inline std::string
227 toString() const
228 {
229 return std::string("[\n")
230 + " " + this->row.vx.toString() + "\n"
231 + " " + this->row.vy.toString() + "\n"
232 + " " + this->row.vz.toString() + "\n"
233 + "]";
234 }
235
236 inline bool
237 operator==(Matrix3 const &other) const
238 {
239 return
240 (this->row.vx == other.row.vx)
241 && (this->row.vy == other.row.vy)
242 && (this->row.vz == other.row.vz);
243 }
244 };
245
246 static inline RZ::Matrix3
247 operator *(RZ::Real k, RZ::Matrix3 M)
248 {
249 return M * k;
250 }
251}
252
253#endif // _MATRIX
Definition: Matrix.h:48
Definition: Vector.h:66