The unit quaternion of a 3x3 rotation matrix (columns: the rotated axes; the inverse of quat_to_matrix), by Shepperd's method (from the largest of w and the vector components, for accuracy).
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| real(kind=wp), | intent(in) | :: | m(3,3) |
rotation matrix (columns: the rotated axes) |
pure function quat_from_matrix(m) result(q) real(wp), intent(in) :: m(3,3) !! rotation matrix (columns: the rotated axes) real(wp) :: q(4) real(wp) :: t, s t = m(1,1) + m(2,2) + m(3,3) if (t >= max(m(1,1), m(2,2), m(3,3))) then s = 2.0_wp * sqrt(1.0_wp + t) q = [(m(3,2) - m(2,3)) / s, (m(1,3) - m(3,1)) / s, (m(2,1) - m(1,2)) / s, 0.25_wp * s] else if (m(1,1) >= m(2,2) .and. m(1,1) >= m(3,3)) then s = 2.0_wp * sqrt(1.0_wp + m(1,1) - m(2,2) - m(3,3)) q = [0.25_wp * s, (m(1,2) + m(2,1)) / s, (m(1,3) + m(3,1)) / s, (m(3,2) - m(2,3)) / s] else if (m(2,2) >= m(3,3)) then s = 2.0_wp * sqrt(1.0_wp - m(1,1) + m(2,2) - m(3,3)) q = [(m(1,2) + m(2,1)) / s, 0.25_wp * s, (m(2,3) + m(3,2)) / s, (m(1,3) - m(3,1)) / s] else s = 2.0_wp * sqrt(1.0_wp - m(1,1) - m(2,2) + m(3,3)) q = [(m(1,3) + m(3,1)) / s, (m(2,3) + m(3,2)) / s, 0.25_wp * s, (m(2,1) - m(1,2)) / s] end if q = q / norm2(q) end function quat_from_matrix