diff --git a/basic-geometry/dual-number.c b/basic-geometry/dual-number.c index 57cec66..90f9bc4 100644 --- a/basic-geometry/dual-number.c +++ b/basic-geometry/dual-number.c @@ -71,3 +71,12 @@ extern inline void bgc_fp64_dual_number_get_mean3(BGC_FP64_DualNumber* const mea extern inline void bgc_fp32_dual_number_interpolate(BGC_FP32_DualNumber* const interpolation, const BGC_FP32_DualNumber* const first, const BGC_FP32_DualNumber* const second, const float phase); extern inline void bgc_fp64_dual_number_interpolate(BGC_FP64_DualNumber* const interpolation, const BGC_FP64_DualNumber* const first, const BGC_FP64_DualNumber* const second, const double phase); + +extern inline void bgc_fp32_dual_number_power(BGC_FP32_DualNumber* const power, const BGC_FP32_DualNumber* const number, const float degree); +extern inline void bgc_fp64_dual_number_power(BGC_FP64_DualNumber* const power, const BGC_FP64_DualNumber* const number, const double degree); + +extern inline void bgc_fp32_dual_number_exponent(BGC_FP32_DualNumber* const exponent, const BGC_FP32_DualNumber* const degree); +extern inline void bgc_fp64_dual_number_exponent(BGC_FP64_DualNumber* const exponent, const BGC_FP64_DualNumber* const degree); + +extern inline int bgc_fp32_dual_number_ln(BGC_FP32_DualNumber* const logarithm, const BGC_FP32_DualNumber* const number); +extern inline int bgc_fp64_dual_number_ln(BGC_FP64_DualNumber* const logarithm, const BGC_FP64_DualNumber* const number); diff --git a/basic-geometry/dual-number.h b/basic-geometry/dual-number.h index 623210b..5a9d0b5 100644 --- a/basic-geometry/dual-number.h +++ b/basic-geometry/dual-number.h @@ -448,4 +448,62 @@ inline void bgc_fp64_dual_number_interpolate(BGC_FP64_DualNumber* const interpol interpolation->dual_part = first->dual_part * counter_phase + second->dual_part * phase; } +// =================== Power ==================== // + +inline void bgc_fp32_dual_number_power(BGC_FP32_DualNumber* const power, const BGC_FP32_DualNumber* const number, const float degree) +{ + const float base = powf(number->real_part, degree - 1.0f); + + power->real_part = base * number->real_part; + power->dual_part = base * number->dual_part * degree; +} + +inline void bgc_fp64_dual_number_power(BGC_FP64_DualNumber* const power, const BGC_FP64_DualNumber* const number, const double degree) +{ + const double base = pow(number->real_part, degree - 1.0); + + power->real_part = base * number->real_part; + power->dual_part = base * number->dual_part * degree; +} + +// ================== Exponent ================== // + +inline void bgc_fp32_dual_number_exponent(BGC_FP32_DualNumber* const exponent, const BGC_FP32_DualNumber* const degree) +{ + exponent->real_part = expf(degree->real_part); + exponent->dual_part = exponent->real_part * degree->dual_part; +} + +inline void bgc_fp64_dual_number_exponent(BGC_FP64_DualNumber* const exponent, const BGC_FP64_DualNumber* const degree) +{ + exponent->real_part = exp(degree->real_part); + exponent->dual_part = exponent->real_part * degree->dual_part; +} + +// ============= Natural Logarithm ============== // + +inline int bgc_fp32_dual_number_ln(BGC_FP32_DualNumber* const logarithm, const BGC_FP32_DualNumber* const number) +{ + if (number->real_part <= 0.0f) { + return BGC_FAILURE; + } + + logarithm->real_part = logf(number->real_part); + logarithm->dual_part = logarithm->real_part * number->dual_part / number->real_part; + + return BGC_SUCCESS; +} + +inline int bgc_fp64_dual_number_ln(BGC_FP64_DualNumber* const logarithm, const BGC_FP64_DualNumber* const number) +{ + if (number->real_part <= 0.0) { + return BGC_FAILURE; + } + + logarithm->real_part = log(number->real_part); + logarithm->dual_part = logarithm->real_part * number->dual_part / number->real_part; + + return BGC_SUCCESS; +} + #endif diff --git a/basic-geometry/dual-quaternion.c b/basic-geometry/dual-quaternion.c index 5edb857..1bfd406 100644 --- a/basic-geometry/dual-quaternion.c +++ b/basic-geometry/dual-quaternion.c @@ -3,6 +3,12 @@ extern inline void bgc_fp32_dual_quaternion_reset(BGC_FP32_DualQuaternion* const quaternion); extern inline void bgc_fp64_dual_quaternion_reset(BGC_FP64_DualQuaternion* const quaternion); +extern inline void bgc_fp32_dual_quaternion_get_square_magnitude(BGC_FP32_DualNumber* const square_magnitude, const BGC_FP32_DualQuaternion* const quaternion); +extern inline void bgc_fp64_dual_quaternion_get_square_magnitude(BGC_FP64_DualNumber* const square_magnitude, const BGC_FP64_DualQuaternion* const quaternion); + +extern inline void bgc_fp32_dual_quaternion_get_magnitude(BGC_FP32_DualNumber* const magnitude, const BGC_FP32_DualQuaternion* const quaternion); +extern inline void bgc_fp64_dual_quaternion_get_magnitude(BGC_FP64_DualNumber* const magnitude, const BGC_FP64_DualQuaternion* const quaternion); + extern inline void bgc_fp32_dual_quaternion_copy(BGC_FP32_DualQuaternion* const destination, const BGC_FP32_DualQuaternion* const source); extern inline void bgc_fp64_dual_quaternion_copy(BGC_FP64_DualQuaternion* const destination, const BGC_FP64_DualQuaternion* const source); diff --git a/basic-geometry/dual-quaternion.h b/basic-geometry/dual-quaternion.h index 9acf475..f8e53a6 100644 --- a/basic-geometry/dual-quaternion.h +++ b/basic-geometry/dual-quaternion.h @@ -18,6 +18,54 @@ inline void bgc_fp64_dual_quaternion_reset(BGC_FP64_DualQuaternion* const quater bgc_fp64_quaternion_reset(&quaternion->dual_part); } +// ============== Square Magnitude ============== // + +inline void bgc_fp32_dual_quaternion_get_square_magnitude(BGC_FP32_DualNumber* const square_magnitude, const BGC_FP32_DualQuaternion* const quaternion) +{ + square_magnitude->real_part = bgc_fp32_quaternion_get_square_magnitude(&quaternion->real_part); + square_magnitude->dual_part = 2.0f * bgc_fp32_quaternion_get_dot_product(&quaternion->real_part, &quaternion->dual_part); +} + +inline void bgc_fp64_dual_quaternion_get_square_magnitude(BGC_FP64_DualNumber* const square_magnitude, const BGC_FP64_DualQuaternion* const quaternion) +{ + square_magnitude->real_part = bgc_fp64_quaternion_get_square_magnitude(&quaternion->real_part); + square_magnitude->dual_part = 2.0 * bgc_fp64_quaternion_get_dot_product(&quaternion->real_part, &quaternion->dual_part); +} + +// ================= Magnitude ================== // + +inline void bgc_fp32_dual_quaternion_get_magnitude(BGC_FP32_DualNumber* const magnitude, const BGC_FP32_DualQuaternion* const quaternion) +{ + const float square_real_part = bgc_fp32_quaternion_get_square_magnitude(&quaternion->real_part); + + if (square_real_part <= BGC_FP32_SQUARE_EPSILON) { + magnitude->real_part = 0.0f; + magnitude->dual_part = 0.0f; + return; + } + + const float real_part = sqrtf(square_real_part); + + magnitude->real_part = real_part; + magnitude->dual_part = bgc_fp32_quaternion_get_dot_product(&quaternion->real_part, &quaternion->dual_part) / real_part; +} + +inline void bgc_fp64_dual_quaternion_get_magnitude(BGC_FP64_DualNumber* const magnitude, const BGC_FP64_DualQuaternion* const quaternion) +{ + const double square_real_part = bgc_fp64_quaternion_get_square_magnitude(&quaternion->real_part); + + if (square_real_part <= BGC_FP64_SQUARE_EPSILON) { + magnitude->real_part = 0.0; + magnitude->dual_part = 0.0; + return; + } + + const double real_part = sqrt(square_real_part); + + magnitude->real_part = real_part; + magnitude->dual_part = bgc_fp64_quaternion_get_dot_product(&quaternion->real_part, &quaternion->dual_part) / real_part; +} + // ==================== Copy ==================== // inline void bgc_fp32_dual_quaternion_copy(BGC_FP32_DualQuaternion* const destination, const BGC_FP32_DualQuaternion* const source)