#include #include "./quaternion.h" extern inline void bgc_fp32_quaternion_reset(BGC_FP32_Quaternion* const quaternion); extern inline void bgc_fp64_quaternion_reset(BGC_FP64_Quaternion* const quaternion); extern inline float bgc_fp32_quaternion_get_square_magnitude(const BGC_FP32_Quaternion* const quaternion); extern inline double bgc_fp64_quaternion_get_square_magnitude(const BGC_FP64_Quaternion* const quaternion); extern inline float bgc_fp32_quaternion_get_magnitude(const BGC_FP32_Quaternion* const quaternion); extern inline double bgc_fp64_quaternion_get_magnitude(const BGC_FP64_Quaternion* const quaternion); extern inline int bgc_fp32_quaternion_is_zero(const BGC_FP32_Quaternion* const quaternion); extern inline int bgc_fp64_quaternion_is_zero(const BGC_FP64_Quaternion* const quaternion); extern inline int bgc_fp32_quaternion_is_unit(const BGC_FP32_Quaternion* const quaternion); extern inline int bgc_fp64_quaternion_is_unit(const BGC_FP64_Quaternion* const quaternion); extern inline int bgc_fp32_quaternion_is_pure(const BGC_FP32_Quaternion* const quaternion); extern inline int bgc_fp64_quaternion_is_pure(const BGC_FP64_Quaternion* const quaternion); extern inline int bgc_fp32_quaternion_is_real(const BGC_FP32_Quaternion* const quaternion); extern inline int bgc_fp64_quaternion_is_real(const BGC_FP64_Quaternion* const quaternion); extern inline void bgc_fp32_quaternion_copy(BGC_FP32_Quaternion* const destination, const BGC_FP32_Quaternion* const source); extern inline void bgc_fp64_quaternion_copy(BGC_FP64_Quaternion* const destination, const BGC_FP64_Quaternion* const source); extern inline void bgc_fp32_quaternion_swap(BGC_FP32_Quaternion* const quarternion1, BGC_FP32_Quaternion* const quarternion2); extern inline void bgc_fp64_quaternion_swap(BGC_FP64_Quaternion* const quarternion1, BGC_FP64_Quaternion* const quarternion2); extern inline void bgc_fp32_quaternion_convert_to_fp64(BGC_FP64_Quaternion* const destination, const BGC_FP32_Quaternion* const source); extern inline void bgc_fp64_quaternion_convert_to_fp32(BGC_FP32_Quaternion* const destination, const BGC_FP64_Quaternion* const source); extern inline void bgc_fp32_quaternion_add(BGC_FP32_Quaternion* const sum, const BGC_FP32_Quaternion* const quaternion1, const BGC_FP32_Quaternion* const quaternion2); extern inline void bgc_fp64_quaternion_add(BGC_FP64_Quaternion* const sum, const BGC_FP64_Quaternion* const quaternion1, const BGC_FP64_Quaternion* const quaternion2); extern inline void bgc_fp32_quaternion_add_scaled(BGC_FP32_Quaternion* const sum, const BGC_FP32_Quaternion* const basic_quaternion, const BGC_FP32_Quaternion* const scalable_quaternion, const float scale); extern inline void bgc_fp64_quaternion_add_scaled(BGC_FP64_Quaternion* const sum, const BGC_FP64_Quaternion* const basic_quaternion, const BGC_FP64_Quaternion* const scalable_quaternion, const double scale); extern inline void bgc_fp32_quaternion_subtract(BGC_FP32_Quaternion* const difference, const BGC_FP32_Quaternion* const minuend, const BGC_FP32_Quaternion* const subtrahend); extern inline void bgc_fp64_quaternion_subtract(BGC_FP64_Quaternion* const difference, const BGC_FP64_Quaternion* const minuend, const BGC_FP64_Quaternion* const subtrahend); extern inline void bgc_fp32_quaternion_subtract_scaled(BGC_FP32_Quaternion* const difference, const BGC_FP32_Quaternion* const basic_quaternion, const BGC_FP32_Quaternion* const scalable_quaternion, const float scale); extern inline void bgc_fp64_quaternion_subtract_scaled(BGC_FP64_Quaternion* const difference, const BGC_FP64_Quaternion* const basic_quaternion, const BGC_FP64_Quaternion* const scalable_quaternion, const double scale); extern inline void bgc_fp32_quaternion_multiply_by_real_number(BGC_FP32_Quaternion* const product, const BGC_FP32_Quaternion* const multiplicand, const float multiplier); extern inline void bgc_fp64_quaternion_multiply_by_real_number(BGC_FP64_Quaternion* const product, const BGC_FP64_Quaternion* const multiplicand, const double multiplier); extern inline void bgc_fp32_quaternion_multiply_by_dual_number(BGC_FP32_DualQuaternion* const product, const BGC_FP32_Quaternion* const multiplicand, const BGC_FP32_DualNumber* const multiplier); extern inline void bgc_fp64_quaternion_multiply_by_dual_number(BGC_FP64_DualQuaternion* const product, const BGC_FP64_Quaternion* const multiplicand, const BGC_FP64_DualNumber* const multiplier); extern inline void bgc_fp32_quaternion_multiply_by_quaternion(BGC_FP32_Quaternion* const product, const BGC_FP32_Quaternion* const left, const BGC_FP32_Quaternion* const right); extern inline void bgc_fp64_quaternion_multiply_by_quaternion(BGC_FP64_Quaternion* const product, const BGC_FP64_Quaternion* const left, const BGC_FP64_Quaternion* const right); extern inline void bgc_fp32_quaternion_multiply_by_dual_quaternion(BGC_FP32_DualQuaternion* const product, const BGC_FP32_Quaternion* const left, const BGC_FP32_DualQuaternion* const right); extern inline void bgc_fp64_quaternion_multiply_by_dual_quaternion(BGC_FP64_DualQuaternion* const product, const BGC_FP64_Quaternion* const left, const BGC_FP64_DualQuaternion* const right); extern inline void bgc_fp32_quaternion_multiply_by_conjugate(BGC_FP32_Quaternion* const product, const BGC_FP32_Quaternion* const left, const BGC_FP32_Quaternion* const right); extern inline void bgc_fp64_quaternion_multiply_by_conjugate(BGC_FP64_Quaternion* const product, const BGC_FP64_Quaternion* const left, const BGC_FP64_Quaternion* const right); extern inline void bgc_fp32_conjugate_quaternion_multiply_by_quaternion(BGC_FP32_Quaternion* const product, const BGC_FP32_Quaternion* const left, const BGC_FP32_Quaternion* const right); extern inline void bgc_fp64_conjugate_quaternion_multiply_by_quaternion(BGC_FP64_Quaternion* const product, const BGC_FP64_Quaternion* const left, const BGC_FP64_Quaternion* const right); extern inline void bgc_fp32_conjugate_quaternion_multiply_by_conjugate(BGC_FP32_Quaternion* const product, const BGC_FP32_Quaternion* const left, const BGC_FP32_Quaternion* const right); extern inline void bgc_fp64_conjugate_quaternion_multiply_by_conjugate(BGC_FP64_Quaternion* const product, const BGC_FP64_Quaternion* const left, const BGC_FP64_Quaternion* const right); extern inline int bgc_fp32_quaternion_divide_by_real_number(BGC_FP32_Quaternion* const quotient, const BGC_FP32_Quaternion* const dividend, const float divisor); extern inline int bgc_fp64_quaternion_divide_by_real_number(BGC_FP64_Quaternion* const quotient, const BGC_FP64_Quaternion* const dividend, const double divisor); extern inline int bgc_fp32_quaternion_divide_by_quaternion(BGC_FP32_Quaternion* const quotient, const BGC_FP32_Quaternion* const divident, const BGC_FP32_Quaternion* const divisor); extern inline int bgc_fp64_quaternion_divide_by_quaternion(BGC_FP64_Quaternion* const quotient, const BGC_FP64_Quaternion* const divident, const BGC_FP64_Quaternion* const divisor); extern inline int bgc_fp32_quaternion_divide_by_conjugate(BGC_FP32_Quaternion* const quotient, const BGC_FP32_Quaternion* const divident, const BGC_FP32_Quaternion* const divisor_to_conjugate); extern inline int bgc_fp64_quaternion_divide_by_conjugate(BGC_FP64_Quaternion* const quotient, const BGC_FP64_Quaternion* const divident, const BGC_FP64_Quaternion* const divisor_to_conjugate); extern inline void bgc_fp32_quaternion_get_mean2(BGC_FP32_Quaternion* const mean, const BGC_FP32_Quaternion* const quaternion1, const BGC_FP32_Quaternion* const quaternion2); extern inline void bgc_fp64_quaternion_get_mean2(BGC_FP64_Quaternion* const mean, const BGC_FP64_Quaternion* const quaternion1, const BGC_FP64_Quaternion* const quaternion2); extern inline void bgc_fp32_quaternion_get_mean3(BGC_FP32_Quaternion* const mean, const BGC_FP32_Quaternion* const quaternion1, const BGC_FP32_Quaternion* const quaternion2, const BGC_FP32_Quaternion* const quaternion3); extern inline void bgc_fp64_quaternion_get_mean3(BGC_FP64_Quaternion* const mean, const BGC_FP64_Quaternion* const quaternion1, const BGC_FP64_Quaternion* const quaternion2, const BGC_FP64_Quaternion* const quaternion3); extern inline void bgc_fp32_quaternion_interpolate(BGC_FP32_Quaternion* const interpolation, const BGC_FP32_Quaternion* const quaternion1, const BGC_FP32_Quaternion* const quaternion2, const float phase); extern inline void bgc_fp64_quaternion_interpolate(BGC_FP64_Quaternion* const interpolation, const BGC_FP64_Quaternion* const quaternion1, const BGC_FP64_Quaternion* const quaternion2, const double phase); extern inline float bgc_fp32_quaternion_get_dot_product(const BGC_FP32_Quaternion* const quaternion1, const BGC_FP32_Quaternion* const quaternion2); extern inline double bgc_fp64_quaternion_get_dot_product(const BGC_FP64_Quaternion* const quaternion1, const BGC_FP64_Quaternion* const quaternion2); extern inline void bgc_fp32_quaternion_conjugate(BGC_FP32_Quaternion* const quaternion); extern inline void bgc_fp64_quaternion_conjugate(BGC_FP64_Quaternion* const quaternion); extern inline void bgc_fp32_quaternion_get_conjugate(BGC_FP32_Quaternion* const conjugate, const BGC_FP32_Quaternion* const quaternion); extern inline void bgc_fp64_quaternion_get_conjugate(BGC_FP64_Quaternion* const conjugate, const BGC_FP64_Quaternion* const quaternion); extern inline void bgc_fp32_quaternion_revert(BGC_FP32_Quaternion* const quaternion); extern inline void bgc_fp64_quaternion_revert(BGC_FP64_Quaternion* const quaternion); extern inline void bgc_fp32_quaternion_get_reverse(BGC_FP32_Quaternion* const reverse, const BGC_FP32_Quaternion* const quaternion); extern inline void bgc_fp64_quaternion_get_reverse(BGC_FP64_Quaternion* const reverse, const BGC_FP64_Quaternion* const quaternion); extern inline int bgc_fp32_quaternion_invert(BGC_FP32_Quaternion* const quaternion); extern inline int bgc_fp64_quaternion_invert(BGC_FP64_Quaternion* const quaternion); extern inline int bgc_fp32_quaternion_get_inverse(BGC_FP32_Quaternion* const inverse, const BGC_FP32_Quaternion* const quaternion); extern inline int bgc_fp64_quaternion_get_inverse(BGC_FP64_Quaternion* const inverse, const BGC_FP64_Quaternion* const quaternion); extern inline int bgc_fp32_quaternion_normalize(BGC_FP32_Quaternion* const quaternion); extern inline int bgc_fp64_quaternion_normalize(BGC_FP64_Quaternion* const quaternion); extern inline int bgc_fp32_quaternion_get_normalized(BGC_FP32_Quaternion* const normalized, const BGC_FP32_Quaternion* const quaternion); extern inline int bgc_fp64_quaternion_get_normalized(BGC_FP64_Quaternion* const normalized, const BGC_FP64_Quaternion* const quaternion); extern inline void _bgc_fp32_versor_turn_vector(BGC_FP32_Vector3* const turned_vector, const BGC_FP32_Quaternion* const quaternion, const BGC_FP32_Vector3* const original_vector); extern inline void _bgc_fp64_versor_turn_vector(BGC_FP64_Vector3* const turned_vector, const BGC_FP64_Quaternion* const quaternion, const BGC_FP64_Vector3* const original_vector); extern inline void _bgc_fp32_versor_turn_vector_back(BGC_FP32_Vector3* const turned_vector, const BGC_FP32_Quaternion* const quaternion, const BGC_FP32_Vector3* const original_vector); extern inline void _bgc_fp64_versor_turn_vector_back(BGC_FP64_Vector3* const turned_vector, const BGC_FP64_Quaternion* const quaternion, const BGC_FP64_Vector3* const original_vector); extern inline int bgc_fp32_quaternion_turn_vector(BGC_FP32_Vector3* const turned_vector, const BGC_FP32_Quaternion* const quaternion, const BGC_FP32_Vector3* const original_vector); extern inline int bgc_fp64_quaternion_turn_vector(BGC_FP64_Vector3* const turned_vector, const BGC_FP64_Quaternion* const quaternion, const BGC_FP64_Vector3* const original_vector); extern inline int bgc_fp32_quaternion_turn_vector_back(BGC_FP32_Vector3* const turned_vector, const BGC_FP32_Quaternion* const quaternion, const BGC_FP32_Vector3* const original_vector); extern inline int bgc_fp64_quaternion_turn_vector_back(BGC_FP64_Vector3* const turned_vector, const BGC_FP64_Quaternion* const quaternion, const BGC_FP64_Vector3* const original_vector); extern inline int bgc_fp32_quaternion_get_both_matrices(BGC_FP32_Matrix3x3* const rotation, BGC_FP32_Matrix3x3* const reverse, const BGC_FP32_Quaternion* const quaternion); extern inline int bgc_fp64_quaternion_get_both_matrices(BGC_FP64_Matrix3x3* const rotation, BGC_FP64_Matrix3x3* const reverse, const BGC_FP64_Quaternion* const quaternion); extern inline int bgc_fp32_quaternion_are_close(const BGC_FP32_Quaternion* const quaternion1, const BGC_FP32_Quaternion* const quaternion2); extern inline int bgc_fp64_quaternion_are_close(const BGC_FP64_Quaternion* const quaternion1, const BGC_FP64_Quaternion* const quaternion2); // =============== Get Exponation =============== // int bgc_fp32_quaternion_get_power(BGC_FP32_Quaternion* const power, const BGC_FP32_Quaternion* const base, const float exponent) { const float ss = base->s * base->s; const float xx = base->x * base->x; const float yy = base->y * base->y; const float zz = base->z * base->z; const float square_vector = xx + (yy + zz); const float square_modulus = (ss + xx) + (yy + zz); // isnan(square_modulus) means checking for NaN value at square_modulus if (isnan(square_modulus)) { return BGC_FAILURE; } if (square_vector <= BGC_FP32_SQUARE_EPSILON) { if (base->s < 0.0f) { return BGC_FAILURE; } power->s = powf(base->s, exponent); power->x = 0.0f; power->y = 0.0f; power->z = 0.0f; return BGC_SUCCESS; } const float vector_modulus = sqrtf(square_vector); const float power_angle = atan2f(vector_modulus, base->s) * exponent; const float power_modulus = powf(square_modulus, 0.5f * exponent); const float multiplier = power_modulus * sinf(power_angle) / vector_modulus; power->s = power_modulus * cosf(power_angle); power->x = base->x * multiplier; power->y = base->y * multiplier; power->z = base->z * multiplier; return BGC_SUCCESS; } int bgc_fp64_quaternion_get_power(BGC_FP64_Quaternion* const power, const BGC_FP64_Quaternion* const base, const double exponent) { const double ss = base->s * base->s; const double xx = base->x * base->x; const double yy = base->y * base->y; const double zz = base->z * base->z; const double square_vector = xx + (yy + zz); const double square_modulus = (ss + xx) + (yy + zz); // isnan(square_modulus) means checking for NaN value at square_modulus if (isnan(square_modulus)) { return BGC_FAILURE; } if (square_vector <= BGC_FP64_SQUARE_EPSILON) { if (base->s < 0.0) { return BGC_FAILURE; } power->s = pow(base->s, exponent); power->x = 0.0; power->y = 0.0; power->z = 0.0; return BGC_SUCCESS; } const double vector_modulus = sqrt(square_vector); const double power_angle = atan2(vector_modulus, base->s) * exponent; const double power_modulus = pow(square_modulus, 0.5 * exponent); const double multiplier = power_modulus * sin(power_angle) / vector_modulus; power->s = power_modulus * cos(power_angle); power->x = base->x * multiplier; power->y = base->y * multiplier; power->z = base->z * multiplier; return BGC_SUCCESS; } // ============ Get Rotation Matrix ============= // int bgc_fp32_quaternion_get_rotation_matrix(BGC_FP32_Matrix3x3* const rotation, const BGC_FP32_Quaternion* const quaternion) { const float ss = quaternion->s * quaternion->s; const float xx = quaternion->x * quaternion->x; const float yy = quaternion->y * quaternion->y; const float zz = quaternion->z * quaternion->z; const float square_modulus = (ss + xx) + (yy + zz); if (square_modulus <= BGC_FP32_SQUARE_EPSILON || isnan(square_modulus)) { bgc_fp32_matrix3x3_make_identity(rotation); return BGC_FAILURE; } const float corrector1 = 1.0f / square_modulus; const float sx = quaternion->s * quaternion->x; const float sy = quaternion->s * quaternion->y; const float sz = quaternion->s * quaternion->z; const float xy = quaternion->x * quaternion->y; const float xz = quaternion->x * quaternion->z; const float yz = quaternion->y * quaternion->z; const float corrector2 = 2.0f * corrector1; rotation->r1c1 = corrector1 * ((ss + xx) - (yy + zz)); rotation->r2c2 = corrector1 * ((ss + yy) - (xx + zz)); rotation->r3c3 = corrector1 * ((ss + zz) - (xx + yy)); rotation->r1c2 = corrector2 * (xy - sz); rotation->r2c3 = corrector2 * (yz - sx); rotation->r3c1 = corrector2 * (xz - sy); rotation->r2c1 = corrector2 * (xy + sz); rotation->r3c2 = corrector2 * (yz + sx); rotation->r1c3 = corrector2 * (xz + sy); return BGC_SUCCESS; } int bgc_fp64_quaternion_get_rotation_matrix(BGC_FP64_Matrix3x3* const rotation, const BGC_FP64_Quaternion* const quaternion) { const double ss = quaternion->s * quaternion->s; const double xx = quaternion->x * quaternion->x; const double yy = quaternion->y * quaternion->y; const double zz = quaternion->z * quaternion->z; const double square_modulus = (ss + xx) + (yy + zz); if (square_modulus <= BGC_FP64_SQUARE_EPSILON || isnan(square_modulus)) { bgc_fp64_matrix3x3_make_identity(rotation); return BGC_FAILURE; } const double corrector1 = 1.0 / square_modulus; const double sx = quaternion->s * quaternion->x; const double sy = quaternion->s * quaternion->y; const double sz = quaternion->s * quaternion->z; const double xy = quaternion->x * quaternion->y; const double xz = quaternion->x * quaternion->z; const double yz = quaternion->y * quaternion->z; const double corrector2 = 2.0 * corrector1; rotation->r1c1 = corrector1 * ((ss + xx) - (yy + zz)); rotation->r2c2 = corrector1 * ((ss + yy) - (xx + zz)); rotation->r3c3 = corrector1 * ((ss + zz) - (xx + yy)); rotation->r1c2 = corrector2 * (xy - sz); rotation->r2c3 = corrector2 * (yz - sx); rotation->r3c1 = corrector2 * (xz - sy); rotation->r2c1 = corrector2 * (xy + sz); rotation->r3c2 = corrector2 * (yz + sx); rotation->r1c3 = corrector2 * (xz + sy); return BGC_SUCCESS; } // ============ Set Rotation Matrix ============= // int bgc_fp32_quaternion_set_rotation_matrix(BGC_FP32_Quaternion* const quaternion, const BGC_FP32_Matrix3x3* const matrix) { if (!bgc_fp32_matrix3x3_is_rotation(matrix)) { return BGC_FAILURE; } const float ss_4 = (1 + matrix->r1c1) + (matrix->r2c2 + matrix->r3c3); const float xx_4 = (1 + matrix->r1c1) - (matrix->r2c2 + matrix->r3c3); const float yy_4 = (1 + matrix->r2c2) - (matrix->r1c1 + matrix->r3c3); const float zz_4 = (1 + matrix->r3c3) - (matrix->r1c1 + matrix->r2c2); const float sx_4 = matrix->r3c2 - matrix->r2c3; const float sy_4 = matrix->r1c3 - matrix->r3c1; const float sz_4 = matrix->r2c1 - matrix->r1c2; const float yz_4 = matrix->r3c2 + matrix->r2c3; const float xz_4 = matrix->r1c3 + matrix->r3c1; const float xy_4 = matrix->r2c1 + matrix->r1c2; float max = ss_4; int index = 0; if (xx_4 > max) { max = xx_4; index = 1; } if (yy_4 > max) { max = yy_4; index = 2; } if (zz_4 > max) { max = zz_4; index = 3; } switch (index) { case 0: quaternion->s = ss_4; quaternion->x = sx_4; quaternion->y = sy_4; quaternion->z = sz_4; break; case 1: quaternion->s = sx_4; quaternion->x = xx_4; quaternion->y = xy_4; quaternion->z = xz_4; break; case 2: quaternion->s = sy_4; quaternion->x = xy_4; quaternion->y = yy_4; quaternion->z = yz_4; break; case 3: quaternion->s = sz_4; quaternion->x = xz_4; quaternion->y = yz_4; quaternion->z = zz_4; break; } if (quaternion->s < 0.0f) { quaternion->s = -quaternion->s; quaternion->x = -quaternion->x; quaternion->y = -quaternion->y; quaternion->z = -quaternion->z; } const float multiplicator = sqrtf(1.0f / bgc_fp32_quaternion_get_square_magnitude(quaternion)); quaternion->s *= multiplicator; quaternion->x *= multiplicator; quaternion->y *= multiplicator; quaternion->z *= multiplicator; return BGC_SUCCESS; } int bgc_fp64_quaternion_set_rotation_matrix(BGC_FP64_Quaternion* const quaternion, const BGC_FP64_Matrix3x3* const matrix) { if (!bgc_fp64_matrix3x3_is_rotation(matrix)) { return BGC_FAILURE; } const double ss_4 = (1 + matrix->r1c1) + (matrix->r2c2 + matrix->r3c3); const double xx_4 = (1 + matrix->r1c1) - (matrix->r2c2 - matrix->r3c3); const double yy_4 = (1 + matrix->r2c2) - (matrix->r1c1 - matrix->r3c3); const double zz_4 = (1 + matrix->r3c3) - (matrix->r1c1 - matrix->r2c2); const double sx_4 = matrix->r3c2 - matrix->r2c3; const double sy_4 = matrix->r1c3 - matrix->r3c1; const double sz_4 = matrix->r2c1 - matrix->r1c2; const double yz_4 = matrix->r3c2 + matrix->r2c3; const double xz_4 = matrix->r1c3 + matrix->r3c1; const double xy_4 = matrix->r2c1 + matrix->r1c2; double max = ss_4; int index = 0; if (xx_4 > max) { max = xx_4; index = 1; } if (yy_4 > max) { max = yy_4; index = 2; } if (zz_4 > max) { max = zz_4; index = 3; } switch (index) { case 0: quaternion->s = ss_4; quaternion->x = sx_4; quaternion->y = sy_4; quaternion->z = sz_4; break; case 1: quaternion->s = sx_4; quaternion->x = xx_4; quaternion->y = xy_4; quaternion->z = xz_4; break; case 2: quaternion->s = sy_4; quaternion->x = xy_4; quaternion->y = yy_4; quaternion->z = yz_4; break; case 3: quaternion->s = sz_4; quaternion->x = xz_4; quaternion->y = yz_4; quaternion->z = zz_4; break; } if (quaternion->s < 0.0) { quaternion->s = -quaternion->s; quaternion->x = -quaternion->x; quaternion->y = -quaternion->y; quaternion->z = -quaternion->z; } const double multiplicator = sqrt(1.0 / bgc_fp64_quaternion_get_square_magnitude(quaternion)); quaternion->s *= multiplicator; quaternion->x *= multiplicator; quaternion->y *= multiplicator; quaternion->z *= multiplicator; return BGC_SUCCESS; } // ============= Get Reverse Matrix ============= // int bgc_fp32_quaternion_get_reverse_matrix(BGC_FP32_Matrix3x3* const reverse, const BGC_FP32_Quaternion* const quaternion) { const float ss = quaternion->s * quaternion->s; const float xx = quaternion->x * quaternion->x; const float yy = quaternion->y * quaternion->y; const float zz = quaternion->z * quaternion->z; const float square_modulus = (ss + xx) + (yy + zz); if (square_modulus <= BGC_FP32_SQUARE_EPSILON || isnan(square_modulus)) { bgc_fp32_matrix3x3_make_identity(reverse); return BGC_FAILURE; } const float corrector1 = 1.0f / square_modulus; const float sx = quaternion->s * quaternion->x; const float sy = quaternion->s * quaternion->y; const float sz = quaternion->s * quaternion->z; const float xy = quaternion->x * quaternion->y; const float xz = quaternion->x * quaternion->z; const float yz = quaternion->y * quaternion->z; const float corrector2 = 2.0f * corrector1; reverse->r1c1 = corrector1 * ((ss + xx) - (yy + zz)); reverse->r2c2 = corrector1 * ((ss + yy) - (xx + zz)); reverse->r3c3 = corrector1 * ((ss + zz) - (xx + yy)); reverse->r1c2 = corrector2 * (xy + sz); reverse->r2c3 = corrector2 * (yz + sx); reverse->r3c1 = corrector2 * (xz + sy); reverse->r2c1 = corrector2 * (xy - sz); reverse->r3c2 = corrector2 * (yz - sx); reverse->r1c3 = corrector2 * (xz - sy); return BGC_SUCCESS; } int bgc_fp64_quaternion_get_reverse_matrix(BGC_FP64_Matrix3x3* const reverse, const BGC_FP64_Quaternion* const quaternion) { const double ss = quaternion->s * quaternion->s; const double xx = quaternion->x * quaternion->x; const double yy = quaternion->y * quaternion->y; const double zz = quaternion->z * quaternion->z; const double square_modulus = (ss + xx) + (yy + zz); if (square_modulus <= BGC_FP64_SQUARE_EPSILON || isnan(square_modulus)) { bgc_fp64_matrix3x3_make_identity(reverse); return BGC_FAILURE; } const double corrector1 = 1.0 / square_modulus; const double sx = quaternion->s * quaternion->x; const double sy = quaternion->s * quaternion->y; const double sz = quaternion->s * quaternion->z; const double xy = quaternion->x * quaternion->y; const double xz = quaternion->x * quaternion->z; const double yz = quaternion->y * quaternion->z; const double corrector2 = 2.0 * corrector1; reverse->r1c1 = corrector1 * ((ss + xx) - (yy + zz)); reverse->r2c2 = corrector1 * ((ss + yy) - (xx + zz)); reverse->r3c3 = corrector1 * ((ss + zz) - (xx + yy)); reverse->r1c2 = corrector2 * (xy + sz); reverse->r2c3 = corrector2 * (yz + sx); reverse->r3c1 = corrector2 * (xz + sy); reverse->r2c1 = corrector2 * (xy - sz); reverse->r3c2 = corrector2 * (yz - sx); reverse->r1c3 = corrector2 * (xz - sy); return BGC_SUCCESS; }