16#ifndef _B2FINITE_ROTATION_H_
17#define _B2FINITE_ROTATION_H_
49 FiniteRotation(
const TP omega_[3])
53 nomega(zero_if_nan(std::
sqrt(
dot_3(omega_, omega_)))),
61 void init(
const TP omega_[3]) {
63 nomega = zero_if_nan(std::sqrt(
dot_3(omega_, omega_)));
66 void get_rotator(TP rotator[3][3]) {
68 for (
int j = 0; j != 3; ++j) {
69 for (
int i = 0; i != 3; ++i) { rotator[j][i] = a[2] * omega[i] * omega[j]; }
70 rotator[j][j] += a[0];
72 const TP w[] = {omega[0] * a[1], omega[1] * a[1], omega[2] * a[1]};
73 add_skew_matrix(w, rotator);
76 void get_d_rotator_d_omega_in_u(
const TP u[3], TP d_rotator_in_u[3][3]) {
79 const TP omega_u =
dot_3(omega, u);
80 const TP s_ident = b[0] * omega_u;
81 const TP s_cross_omega = b[2] * omega_u;
82 for (
int j = 0; j != 3; ++j) {
83 for (
int i = 0; i != 3; ++i) {
84 d_rotator_in_u[j][i] = a[2] * (u[i] * omega[j] + u[j] * omega[i])
85 + s_cross_omega * omega[i] * omega[j];
87 d_rotator_in_u[j][j] += s_ident;
91 const TP omega_s = b[1] * omega_u;
92 for (
int i = 0; i != 3; ++i) { w[i] = a[1] * u[i] + omega_s * omega[i]; }
93 add_skew_matrix(w, d_rotator_in_u);
97 void get_d_trans_rotator_d_omega_in_u(
const TP u[3], TP d_trans_rotator_in_u[3][3]) {
100 const TP omega_u =
dot_3(omega, u);
101 const TP s_ident = b[0] * omega_u;
102 const TP s_cross_omega = b[2] * omega_u;
103 for (
int j = 0; j != 3; ++j) {
104 for (
int i = 0; i != 3; ++i) {
105 d_trans_rotator_in_u[j][i] = a[2] * (u[i] * omega[j] + u[j] * omega[i])
106 + s_cross_omega * omega[i] * omega[j];
108 d_trans_rotator_in_u[j][j] += s_ident;
112 const TP omega_s = -b[1] * omega_u;
113 for (
int i = 0; i != 3; ++i) { w[i] = -a[1] * u[i] + omega_s * omega[i]; }
114 add_skew_matrix(w, d_trans_rotator_in_u);
118 void get_d2_rotator_d2_omega_in_uv(
const TP u[3],
const TP v[3], TP d_rotator_in_uv[3][3]) {
122 const TP u_v =
dot_3(u, v);
123 const TP omega_u =
dot_3(omega, u);
124 const TP omega_v =
dot_3(omega, v);
125 const TP omega_v_omega_u = omega_v * omega_u;
126 const TP b2_omega_u = b[2] * omega_u;
127 const TP b2_omega_v = b[2] * omega_v;
128 const TP b2_u_v_c2_omega_v_omega_u = b[2] * u_v + c[2] * omega_v_omega_u;
129 const TP s_ident = b[0] * u_v + c[0] * omega_v_omega_u;
130 for (
int j = 0; j != 3; ++j) {
131 for (
int i = 0; i != 3; ++i) {
132 d_rotator_in_uv[j][i] = a[2] * (u[i] * v[j] + u[j] * v[i])
133 + b2_omega_u * (v[i] * omega[j] + v[j] * omega[i])
134 + b2_omega_v * (u[i] * omega[j] + u[j] * omega[i])
135 + b2_u_v_c2_omega_v_omega_u * omega[i] * omega[j];
137 d_rotator_in_uv[j][j] += s_ident;
141 const TP us = b[1] * omega_v;
142 const TP vs = b[1] * omega_u;
143 const TP omega_s = b[1] * u_v + c[1] * omega_v_omega_u;
144 for (
int i = 0; i != 3; ++i) { w[i] = us * u[i] + vs * v[i] + omega_s * omega[i]; }
145 add_skew_matrix(w, d_rotator_in_uv);
151 void get_T(TP T[3][3]) {
153 for (
int j = 0; j != 3; ++j) {
154 for (
int i = 0; i != 3; ++i) { T[j][i] = a[3] * omega[i] * omega[j]; }
157 const TP w[] = {omega[0] * a[2], omega[1] * a[2], omega[2] * a[2]};
158 add_skew_matrix(w, T);
161 void get_d_T_d_omega_in_u(
const TP u[3], TP d_T_in_u[3][3]) {
164 const TP omega_u =
dot_3(omega, u);
165 const TP s_ident = b[1] * omega_u;
166 const TP s_cross_omega = b[3] * omega_u;
167 for (
int j = 0; j != 3; ++j) {
168 for (
int i = 0; i != 3; ++i) {
169 d_T_in_u[j][i] = a[3] * (u[i] * omega[j] + u[j] * omega[i])
170 + s_cross_omega * omega[i] * omega[j];
172 d_T_in_u[j][j] += s_ident;
176 const TP omega_s = b[2] * omega_u;
177 for (
int i = 0; i != 3; ++i) { w[i] = a[2] * u[i] + omega_s * omega[i]; }
178 add_skew_matrix(w, d_T_in_u);
182 void get_d_trans_T_d_omega_in_u(
const TP u[3], TP d_trans_T_in_u[3][3]) {
185 const TP omega_u =
dot_3(omega, u);
186 const TP s_ident = b[1] * omega_u;
187 const TP s_cross_omega = b[3] * omega_u;
188 for (
int j = 0; j != 3; ++j) {
189 for (
int i = 0; i != 3; ++i) {
190 d_trans_T_in_u[j][i] = a[3] * (u[i] * omega[j] + u[j] * omega[i])
191 + s_cross_omega * omega[i] * omega[j];
193 d_trans_T_in_u[j][j] += s_ident;
197 const TP omega_s = -b[2] * omega_u;
198 for (
int i = 0; i != 3; ++i) { w[i] = -a[2] * u[i] + omega_s * omega[i]; }
199 add_skew_matrix(w, d_trans_T_in_u);
203 void get_d2_T_d2_omega_in_uv(
const TP u[3],
const TP v[3], TP d_T_in_uv[3][3]) {
207 const TP u_v =
dot_3(u, v);
208 const TP omega_u =
dot_3(omega, u);
209 const TP omega_v =
dot_3(omega, v);
210 const TP omega_v_omega_u = omega_v * omega_u;
211 const TP b2_omega_u = b[3] * omega_u;
212 const TP b2_omega_v = b[3] * omega_v;
213 const TP b2_u_v_c2_omega_v_omega_u = b[3] * u_v + c[3] * omega_v_omega_u;
214 const TP s_ident = b[1] * u_v + c[1] * omega_v_omega_u;
215 for (
int j = 0; j != 3; ++j) {
216 for (
int i = 0; i != 3; ++i) {
217 d_T_in_uv[j][i] = a[3] * (u[i] * v[j] + u[j] * v[i])
218 + b2_omega_u * (v[i] * omega[j] + v[j] * omega[i])
219 + b2_omega_v * (u[i] * omega[j] + u[j] * omega[i])
220 + b2_u_v_c2_omega_v_omega_u * omega[i] * omega[j];
222 d_T_in_uv[j][j] += s_ident;
226 const TP us = b[2] * omega_v;
227 const TP vs = b[2] * omega_u;
228 const TP omega_s = b[2] * u_v + c[2] * omega_v_omega_u;
229 for (
int i = 0; i != 3; ++i) { w[i] = us * u[i] + vs * v[i] + omega_s * omega[i]; }
230 add_skew_matrix(w, d_T_in_uv);
234 void get_d_rotator_d_omega_in_u_d_u_in_a(
const TP va[3], TP m[3][3]) {
237 const TP omega_va =
dot_3(omega, va);
238 const TP s_ident = a[2] * omega_va;
239 const TP b2_omega_va = b[2] * omega_va;
240 TP omega_cross_va[3];
242 for (
int j = 0; j != 3; ++j) {
243 for (
int i = 0; i != 3; ++i) {
244 m[j][i] = a[2] * omega[i] * va[j] + b[0] * va[i] * omega[j]
245 + b[1] * omega_cross_va[i] * omega[j] + b2_omega_va * omega[i] * omega[j];
249 const TP w[] = {-va[0] * a[1], -va[1] * a[1], -va[2] * a[1]};
250 add_skew_matrix(w, m);
253 void get_d_T_d_omega_in_u_d_u_in_a(
const TP va[3], TP m[3][3]) {
256 const TP omega_va =
dot_3(omega, va);
257 const TP s_ident = a[3] * omega_va;
258 const TP b2_omega_va = b[3] * omega_va;
259 TP omega_cross_va[3];
261 for (
int j = 0; j != 3; ++j) {
262 for (
int i = 0; i != 3; ++i) {
263 m[j][i] = a[3] * omega[i] * va[j] + b[1] * va[i] * omega[j]
264 + b[2] * omega_cross_va[i] * omega[j] + b2_omega_va * omega[i] * omega[j];
268 const TP w[] = {-va[0] * a[2], -va[1] * a[2], -va[2] * a[2]};
269 add_skew_matrix(w, m);
272 void get_d_trans_rotator_d_omega_in_u_d_u_in_a(
const TP va[3], TP m[3][3]) {
275 const TP omega_va =
dot_3(omega, va);
276 const TP s_ident = a[2] * omega_va;
277 const TP b2_omega_va = b[2] * omega_va;
278 TP omega_cross_va[3];
280 for (
int j = 0; j != 3; ++j) {
281 for (
int i = 0; i != 3; ++i) {
282 m[j][i] = a[2] * omega[i] * va[j] + b[0] * va[i] * omega[j]
283 - b[1] * omega_cross_va[i] * omega[j] + b2_omega_va * omega[i] * omega[j];
287 const TP w[] = {va[0] * a[1], va[1] * a[1], va[2] * a[1]};
288 add_skew_matrix(w, m);
291 void get_d_trans_T_d_omega_in_u_d_u_in_a(
const TP va[3], TP m[3][3]) {
294 const TP omega_va =
dot_3(omega, va);
295 const TP s_ident = a[3] * omega_va;
296 const TP b2_omega_va = b[3] * omega_va;
297 TP omega_cross_va[3];
299 for (
int j = 0; j != 3; ++j) {
300 for (
int i = 0; i != 3; ++i) {
301 m[j][i] = a[3] * omega[i] * va[j] + b[1] * va[i] * omega[j]
302 - b[2] * omega_cross_va[i] * omega[j] + b2_omega_va * omega[i] * omega[j];
306 const TP w[] = {va[0] * a[2], va[1] * a[2], va[2] * a[2]};
307 add_skew_matrix(w, m);
310 void get_d2_rotator_d2_omega_in_uv_d_uv_in_ab(
const TP va[3],
const TP vb[3], TP m[3][3]) {
316 TP omega_cross_va[3];
318 const TP omega_va =
dot_3(omega, va);
319 const TP omega_vb =
dot_3(omega, vb);
320 const TP va_vb =
dot_3(va, vb);
321 const TP omega_cross_va_vb =
dot_3(omega_cross_va, vb);
322 const TP omega_va_omega_vb = omega_va * omega_vb;
323 const TP s_ident = b[0] * va_vb + b[1] * omega_cross_va_vb + b[2] * omega_va_omega_vb;
324 const TP s_omega_omega = c[0] * va_vb + c[1] * omega_cross_va_vb + c[2] * omega_va_omega_vb;
325 const TP b2_omega_va = b[2] * omega_va;
326 const TP b2_omega_vb = b[2] * omega_vb;
327 for (
int j = 0; j != 3; ++j) {
328 for (
int i = 0; i != 3; ++i) {
329 m[j][i] = a[2] * (va[i] * vb[j] + vb[i] * va[j])
330 + b[1] * (va_cross_vb[i] * omega[j] + omega[i] * va_cross_vb[j])
331 + b2_omega_va * (vb[i] * omega[j] + omega[i] * vb[j])
332 + b2_omega_vb * (va[i] * omega[j] + omega[i] * va[j])
333 + s_omega_omega * omega[i] * omega[j];
339 void get_d2_T_d2_omega_in_uv_d_uv_in_ab(
const TP va[3],
const TP vb[3], TP m[3][3]) {
345 TP omega_cross_va[3];
347 const TP omega_va =
dot_3(omega, va);
348 const TP omega_vb =
dot_3(omega, vb);
349 const TP va_vb =
dot_3(va, vb);
350 const TP omega_cross_va_vb =
dot_3(omega_cross_va, vb);
351 const TP omega_va_omega_vb = omega_va * omega_vb;
352 const TP s_ident = b[1] * va_vb + b[2] * omega_cross_va_vb + b[3] * omega_va_omega_vb;
353 const TP s_omega_omega = c[1] * va_vb + c[2] * omega_cross_va_vb + c[3] * omega_va_omega_vb;
354 const TP b2_omega_va = b[3] * omega_va;
355 const TP b2_omega_vb = b[3] * omega_vb;
356 for (
int i = 0; i != 3; ++i) {
357 for (
int j = 0; j != 3; ++j) {
358 m[i][j] = a[3] * (va[i] * vb[j] + vb[i] * va[j])
359 + b[2] * (va_cross_vb[i] * omega[j] + omega[i] * va_cross_vb[j])
360 + b2_omega_va * (vb[i] * omega[j] + omega[i] * vb[j])
361 + b2_omega_vb * (va[i] * omega[j] + omega[i] * va[j])
362 + s_omega_omega * omega[i] * omega[j];
369 static TP zero_if_nan(
const TP v) {
370 if (v == v) {
return v; }
374 void compute_a(
int min,
int max) {
375 if (min < adef_min) {
376 for (
int i = min; i < adef_min; ++i) { a[i] = get_a(i, nomega); }
379 if (max > adef_max) {
380 for (
int i = std::max(min, adef_max); i < max; ++i) { a[i] = get_a(i, nomega); }
385 void compute_b(
int min,
int max) {
386 if (min < bdef_min) {
387 for (
int i = min; i < bdef_min; ++i) { b[i] = get_b(i, nomega); }
390 if (max > bdef_max) {
391 for (
int i = std::max(min, bdef_max); i < max; ++i) { b[i] = get_b(i, nomega); }
396 void compute_c(
int min,
int max) {
397 if (min < cdef_min) {
398 for (
int i = min; i < cdef_min; ++i) { c[i] = get_c(i, nomega); }
401 if (max > cdef_max) {
402 for (
int i = std::max(min, cdef_max); i < max; ++i) { c[i] = get_c(i, nomega); }
408 static TP get_a(
const int i,
const TP omega) {
409 assert(omega == omega);
410 if (omega >= min_for_trigo) {
413 return std::cos(omega);
415 return std::sin(omega) / omega;
417 return (1 -
cos(omega)) / (omega * omega);
419 return (omega -
sin(omega)) / (omega * omega * omega);
423 const TP momega2 = -omega * omega;
424 assert(i >= 0 && i < 8);
425 TP t = TP(1) / factorial[i];
429 t *= momega2 / ((k2_i - 1) * k2_i);
430 const TP new_r = r + t;
431 if (new_r == r) {
return r; }
439 static TP get_b(
const int i,
const TP omega) {
440 const TP omega2 = omega * omega;
441 if (omega >= min_for_trigo) {
444 return -
sin(omega) / omega;
446 return (omega *
cos(omega) -
sin(omega)) / (omega2 * omega);
448 return (omega *
sin(omega) - 2 + 2 *
cos(omega)) / (omega2 * omega2);
450 return (3 *
sin(omega) - 2 * omega - omega *
cos(omega))
451 / (omega2 * omega2 * omega);
455 assert(i >= 0 && 2 + i < 8);
456 const TP momega2 = -omega2;
458 TP t = -TP(1) / factorial[2 + i];
461 t *= momega2 / ((k2_2 + i - 1) * (k2_2 + i));
462 const TP new_r = r + k2_2 * t;
463 if (new_r == r) {
return r; }
471 static TP get_c(
const int i,
const TP omega) {
472 const TP omega2 = omega * omega;
473 if (omega >= min_for_trigo) {
474 const TP omega4 = omega2 * omega2;
477 return (
sin(omega) - omega *
cos(omega)) / (omega2 * omega);
479 return ((3 - omega2) *
sin(omega) - 3 * omega *
cos(omega)) / (omega4 * omega);
481 return (8 + (omega2 - 8) *
cos(omega) - 5 * omega *
sin(omega))
484 return (8 * omega + 7 * omega *
cos(omega) + (omega2 - 15) *
sin(omega))
485 / (omega4 * omega2 * omega);
489 const TP momega2 = -omega2;
492 assert(i >= 0 && 4 + i < 8);
493 TP t = TP(1) / factorial[4 + i];
496 t *= momega2 / ((i_4_2k - 1) * i_4_2k);
497 const TP new_r = r + 4 * (k + 1) * (k + 2) * t;
498 if (new_r == r) {
return r; }
507 static void add_skew_matrix(
const TP w[3], TP r[3][3]) {
516 static const TP min_for_trigo;
518 static constexpr int factorial[8] = {1, 1, 2, 6, 24, 120, 720, 5040};
533template <
typename TP>
534const TP FiniteRotation<TP>::min_for_trigo = TP(1);
536template <
typename TP>
537constexpr int FiniteRotation<TP>::factorial[8];
544template <
typename TP>
546 const TP c0 = cos(e[0]);
547 const TP c1 = cos(e[1]);
548 const TP c2 = cos(e[2]);
549 const TP s0 = sin(e[0]);
550 const TP s1 = sin(e[1]);
551 const TP s2 = sin(e[2]);
552 rotator[0][0] = c1 * c2;
553 rotator[0][1] = c1 * s2;
555 rotator[1][0] = -c0 * s2 + s0 * s1 * c2;
556 rotator[1][1] = c0 * c2 + s0 * s1 * s2;
557 rotator[1][2] = s0 * c1;
558 rotator[2][0] = s0 * s2 + c0 * s1 * c2;
559 rotator[2][1] = -s0 * c2 + c0 * s1 * s2;
560 rotator[2][2] = c0 * c1;
568template <
typename TP>
570 if (abs(rotator[0][2]) < 1 - 1e-15) {
571 e[1] = -asin(rotator[0][2]);
572 const TP inv_ce1 = TP(1) / cos(e[1]);
573 e[0] = atan2(rotator[1][2] * inv_ce1, rotator[2][2] * inv_ce1);
574 e[2] = atan2(rotator[0][1] * inv_ce1, rotator[0][0] * inv_ce1);
577 if (rotator[0][2] < 0) {
579 e[0] = atan2(rotator[1][0], rotator[2][0]);
582 e[0] = atan2(-rotator[1][0], -rotator[2][0]);
587template <
typename TP>
588inline void rotator_to_quaternion(
const TP rotator[3][3], TP q[4]) {
589 if (rotator[1][1] > -rotator[2][2] && rotator[0][0] > -rotator[1][1]
590 && rotator[0][0] > -rotator[2][2]) {
591 const TP s = 0.5 * sqrt(1.0 + rotator[0][0] + rotator[1][1] + rotator[2][2]);
592 const TP invs = 0.25 / s;
594 q[1] = (rotator[2][1] - rotator[1][2]) * invs;
595 q[2] = (rotator[0][2] - rotator[2][0]) * invs;
596 q[3] = (rotator[1][0] - rotator[0][1]) * invs;
598 rotator[1][1] < -rotator[2][2] && rotator[0][0] > rotator[1][1]
599 && rotator[0][0] > rotator[2][2]) {
600 const TP s = 0.5 *
sqrt(1.0 + rotator[0][0] - rotator[1][1] - rotator[2][2]);
601 const TP invs = 0.25 / s;
602 q[0] = (rotator[2][1] - rotator[1][2]) * invs;
604 q[2] = (rotator[1][0] + rotator[0][1]) * invs;
605 q[3] = (rotator[0][2] + rotator[2][0]) * invs;
607 rotator[1][1] > rotator[2][2] && rotator[0][0] < rotator[1][1]
608 && rotator[0][0] < -rotator[2][2]) {
609 const TP s = 0.5 *
sqrt(1.0 - rotator[0][0] + rotator[1][1] - rotator[2][2]);
610 const TP invs = 0.25 / s;
611 q[0] = (rotator[0][2] - rotator[2][0]) * invs;
612 q[1] = (rotator[1][0] + rotator[0][1]) * invs;
614 q[3] = (rotator[2][1] + rotator[1][2]) * invs;
616 rotator[1][1] < rotator[2][2] && rotator[0][0] < -rotator[1][1]
617 && rotator[0][0] < rotator[2][2]) {
618 const TP s = 0.5 *
sqrt(1.0 - rotator[0][0] - rotator[1][1] + rotator[2][2]);
619 const TP invs = 0.25 / s;
620 q[0] = (rotator[1][0] - rotator[0][1]) * invs;
621 q[1] = (rotator[2][0] + rotator[0][2]) * invs;
622 q[2] = (rotator[2][1] + rotator[1][2]) * invs;
629template <
typename TP>
630inline void rotation_vector_to_quaternion(
631 const TP rotation_vector[3], TP quaternion[4], TP d_quaternion_d_rotation_vector[3][4] = 0) {
632 const TP omega =
sqrt(
dot_3(rotation_vector, rotation_vector));
633 const TP omega_2 = omega / 2;
634 const TP c_v2 =
cos(omega_2);
635 const TP s_omega_2_omega_2 = FiniteRotation<TP>::get_a(1, omega_2);
637 quaternion[0] = c_v2;
638 const TP s = s_omega_2_omega_2 * 0.5;
639 for (
int i = 0; i != 3; ++i) { quaternion[i + 1] = rotation_vector[i] * s; }
641 if (d_quaternion_d_rotation_vector) {
642 const TP a = s_omega_2_omega_2 / 4;
643 const TP b = omega < std::numeric_limits<TP>::epsilon()
645 : (c_v2 * omega - 2 *
sin(omega_2)) / (2 * omega * omega * omega);
646 for (
int j = 0; j != 3; ++j) {
647 d_quaternion_d_rotation_vector[j][0] = -a * rotation_vector[j];
648 for (
int i = 0; i != 3; ++i) {
649 d_quaternion_d_rotation_vector[j][i + 1] =
650 b * rotation_vector[i] * rotation_vector[j];
652 d_quaternion_d_rotation_vector[j][j + 1] += 2 * a;
657template <
typename TP>
658inline void quaternion_to_rotation_vector(
659 const TP quaternion[4], TP rotation_vector[3], TP d_rotator_vector_d_quaternion[4][3] = 0) {
660 const TP n2 = 1 - quaternion[0] * quaternion[0];
661 const TP n =
sqrt(n2);
662 const TP s = n < std::numeric_limits<TP>::epsilon() ? TP(2) : TP(2) *
acos(quaternion[0]) / n;
663 if (rotation_vector) {
664 for (
int i = 0; i != 3; ++i) { rotation_vector[i] = s * quaternion[i + 1]; }
666 if (d_rotator_vector_d_quaternion) {
667 const TP c = n < std::numeric_limits<TP>::epsilon() ? TP(0) : TP(1) / n2;
668 for (
int i = 0; i != 3; ++i) {
669 d_rotator_vector_d_quaternion[0][i] = c * quaternion[i + 1] * (s * quaternion[0] - 2);
670 for (
int j = 1; j != 4; ++j) { d_rotator_vector_d_quaternion[j][i] = 0; }
671 d_rotator_vector_d_quaternion[i + 1][i] = s;
676template <
typename TP>
677inline TP quaternion_norm(
const TP quaternion[4]) {
678 return sqrt(quaternion[0] * quaternion[0] +
dot_3(quaternion + 1, quaternion + 1));
681template <
typename TP>
682inline void quaternion_renormalisation(TP q[4]) {
683 const TP s = TP(1) /
sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]);
684 for (
int i = 0; i != 4; ++i) { q[i] *= s; }
687template <
typename TP>
688inline void quaternion_to_rotator(
const TP quaternion[4], TP rotator[3][3]) {
689 const TP s = 2 / quaternion_norm(quaternion);
690 for (
int j = 0; j != 3; ++j) {
691 for (
int i = 0; i != 3; ++i) { rotator[j][i] = s * quaternion[i + 1] * quaternion[j + 1]; }
693 const TP sq = s * quaternion[0];
694 const TP sq2_1 = sq * quaternion[0] - 1;
695 rotator[0][0] += sq2_1;
696 rotator[0][1] -= sq * quaternion[3];
697 rotator[0][2] += sq * quaternion[2];
698 rotator[1][0] += sq * quaternion[3];
699 rotator[1][1] += sq2_1;
700 rotator[1][2] -= sq * quaternion[1];
701 rotator[2][0] -= sq * quaternion[2];
702 rotator[2][1] += sq * quaternion[1];
703 rotator[2][2] += sq2_1;
706template <
typename TP>
707inline void quaternion_add(
const TP qa[4],
const TP qb[4], TP qc[4]) {
708 for (
int i = 0; i != 4; ++i) { qc[i] = qa[i] + qb[i]; }
711template <
typename TP>
712inline TP quaternion_dot(
const TP qa[4],
const TP qb[4]) {
713 return qa[0] * qb[0] + qa[1] * qb[1] + qa[2] * qb[2] + qa[3] * qb[3];
716template <
typename TP>
717inline void quaternion_product(
const TP qa[4],
const TP qb[4], TP qc[4]) {
718 qc[0] = qa[0] * qb[0] - qa[1] * qb[1] - qa[2] * qb[2] - qa[3] * qb[3];
719 qc[1] = qa[0] * qb[1] + qa[1] * qb[0] - qa[2] * qb[3] + qa[3] * qb[2];
720 qc[2] = qa[0] * qb[2] + qa[1] * qb[3] + qa[2] * qb[0] - qa[3] * qb[1];
721 qc[3] = qa[0] * qb[3] - qa[1] * qb[2] + qa[2] * qb[1] + qa[3] * qb[0];
724template <
typename TP>
725inline void d_quaternion_product_d_qa(
const TP qb[4], TP d_qc_d_qa[4][4]) {
726 d_qc_d_qa[0][0] = qb[0];
727 d_qc_d_qa[0][1] = qb[1];
728 d_qc_d_qa[0][2] = qb[2];
729 d_qc_d_qa[0][3] = qb[3];
730 d_qc_d_qa[1][0] = -qb[1];
731 d_qc_d_qa[1][1] = qb[0];
732 d_qc_d_qa[1][2] = qb[3];
733 d_qc_d_qa[1][3] = -qb[2];
734 d_qc_d_qa[2][0] = -qb[2];
735 d_qc_d_qa[2][1] = -qb[3];
736 d_qc_d_qa[2][2] = qb[0];
737 d_qc_d_qa[2][3] = qb[1];
738 d_qc_d_qa[3][0] = -qb[3];
739 d_qc_d_qa[3][1] = qb[2];
740 d_qc_d_qa[3][2] = -qb[1];
741 d_qc_d_qa[3][3] = qb[0];
744template <
typename TP>
745inline void d_quaternion_product_d_qb(
const TP qa[4], TP d_qc_d_qb[4][4]) {
746 d_qc_d_qb[0][0] = qa[0];
747 d_qc_d_qb[0][1] = qa[1];
748 d_qc_d_qb[0][2] = qa[2];
749 d_qc_d_qb[0][3] = qa[3];
750 d_qc_d_qb[1][0] = -qa[1];
751 d_qc_d_qb[1][1] = qa[0];
752 d_qc_d_qb[1][2] = -qa[3];
753 d_qc_d_qb[1][3] = qa[2];
754 d_qc_d_qb[2][0] = -qa[2];
755 d_qc_d_qb[2][1] = qa[3];
756 d_qc_d_qb[2][2] = qa[0];
757 d_qc_d_qb[2][3] = -qa[1];
758 d_qc_d_qb[3][0] = -qa[3];
759 d_qc_d_qb[3][1] = -qa[2];
760 d_qc_d_qb[3][2] = qa[1];
761 d_qc_d_qb[3][3] = qa[0];
764template <
typename TP>
765inline void quaternion_inverse(
const TP q[4], TP qinv[4]) {
766 const TP s = TP(1) / quaternion_norm(q);
768 for (
int i = 1; i != 4; ++i) { qinv[i] = -s * q[i]; }
csda< T > acos(const csda< T > &z)
Arc cosine of a csda number.
Definition b2csda.H:431
csda< T > sin(const csda< T > &a)
Sine of a csda number.
Definition b2csda.H:402
csda< T > sqrt(const csda< T > &a)
Square root of a csda number.
Definition b2csda.H:396
csda< T > cos(const csda< T > &a)
Cosine of a csda number.
Definition b2csda.H:410
Contains the base classes for implementing Finite Elements.
Definition b2boundary_condition.H:32
void rotator_to_euler_angle(const TP rotator[3][3], TP e[3])
Definition b2finite_rotation.H:569
void outer_product_3(const T1 a[3], const T2 b[3], T3 c[3])
Definition b2tensor_calculus.H:389
void euler_angles_to_rotation_matrix(const TP e[3], TP rotator[3][3])
Definition b2finite_rotation.H:545
T dot_3(const T a[3], const T b[3])
Definition b2tensor_calculus.H:328