bgc-c/basic-geometry/quaternion.c

230 lines
17 KiB
C

#include <math.h>
#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 void bgc_fp32_quaternion_make_unit(BGC_FP32_Quaternion* const quaternion);
extern inline void bgc_fp64_quaternion_make_unit(BGC_FP64_Quaternion* const quaternion);
extern inline void bgc_fp32_quaternion_set_values(BGC_FP32_Quaternion* const quaternion, const float s, const float x, const float y, const float z);
extern inline void bgc_fp64_quaternion_set_values(BGC_FP64_Quaternion* const quaternion, const double s, const double x, const double y, const double z);
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 void _bgc_fp32_versor_get_rotation_matrix(BGC_FP32_Matrix3x3* const matrix, const BGC_FP32_Quaternion* const versor);
extern inline void _bgc_fp64_versor_get_rotation_matrix(BGC_FP64_Matrix3x3* const matrix, const BGC_FP64_Quaternion* const versor);
extern inline void _bgc_fp32_versor_get_reverse_matrix(BGC_FP32_Matrix3x3* const matrix, const BGC_FP32_Quaternion* const versor);
extern inline void _bgc_fp64_versor_get_reverse_matrix(BGC_FP64_Matrix3x3* const matrix, const BGC_FP64_Quaternion* const versor);
extern inline int bgc_fp32_quaternion_get_rotation_matrix(BGC_FP32_Matrix3x3* const rotation, const BGC_FP32_Quaternion* const quaternion);
extern inline int bgc_fp64_quaternion_get_rotation_matrix(BGC_FP64_Matrix3x3* const rotation, const BGC_FP64_Quaternion* const quaternion);
extern inline int bgc_fp32_quaternion_get_reverse_matrix(BGC_FP32_Matrix3x3* const reverse, const BGC_FP32_Quaternion* const quaternion);
extern inline int bgc_fp64_quaternion_get_reverse_matrix(BGC_FP64_Matrix3x3* const reverse, const BGC_FP64_Quaternion* const quaternion);
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;
}