From 74be89f1f85aba78a2eb72dff3f4ccf080f64a76 Mon Sep 17 00:00:00 2001 From: Andrey Pokidov <9942846+Morgend@users.noreply.github.com> Date: Wed, 26 Feb 2025 16:27:33 +0700 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=B8=D0=BC=D0=B5?= =?UTF-8?q?=D0=BD=D0=BE=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20tangent=20pair=20?= =?UTF-8?q?=D0=B2=20=D1=87=D0=B8=D1=81=D0=BB=D0=B0=20=D0=9A=D0=BE=D1=82?= =?UTF-8?q?=D1=81=D0=B0,=20=D0=B2=D1=8B=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=BA=D0=BE=D0=BC=D0=BF=D0=BB=D0=B5=D0=BA=D1=81?= =?UTF-8?q?=D0=BD=D1=8B=D1=85=20=D1=87=D0=B8=D1=81=D0=B5=D0=BB=20=D0=B8?= =?UTF-8?q?=D0=B7=20=D0=B4=D0=B2=D1=83=D0=BC=D0=B5=D1=80=D0=BD=D1=8B=D1=85?= =?UTF-8?q?=20=D0=B2=D0=B5=D0=BA=D1=82=D0=BE=D1=80=D0=BE=D0=B2,=20=D0=B4?= =?UTF-8?q?=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=B2?= =?UTF-8?q?=D0=BE=D0=B7=D0=B2=D0=B5=D0=B4=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=B2?= =?UTF-8?q?=20=D1=81=D0=BF=D0=B5=D0=B1=D0=B5=D0=BD=D1=8C=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=B2=D0=B5=D1=80=D0=BE=D1=81=D0=BE=D1=80=D0=B2=20?= =?UTF-8?q?=D0=B8=20=D1=87=D0=B8=D1=81=D0=B5=D0=BB=20=D0=9A=D0=BE=D1=82?= =?UTF-8?q?=D1=81=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- basic-geometry-dev/main.c | 33 +- basic-geometry/basic-geometry.cbp | 12 +- basic-geometry/basic-geometry.h | 29 +- basic-geometry/basic-geometry.vcxproj | 7 +- basic-geometry/basic-geometry.vcxproj.filters | 18 +- basic-geometry/complex.c | 124 ++++ basic-geometry/complex.h | 531 ++++++++++++++++++ basic-geometry/cotes-number.c | 82 +++ basic-geometry/cotes-number.h | 374 ++++++++++++ basic-geometry/quaternion.c | 4 + basic-geometry/quaternion.h | 2 + basic-geometry/tangent-pair.c | 79 --- basic-geometry/tangent-pair.h | 352 ------------ basic-geometry/vector2.c | 54 -- basic-geometry/vector2.h | 114 ---- basic-geometry/versor.c | 58 +- basic-geometry/versor.h | 6 + 17 files changed, 1233 insertions(+), 646 deletions(-) create mode 100644 basic-geometry/complex.c create mode 100644 basic-geometry/complex.h create mode 100644 basic-geometry/cotes-number.c create mode 100644 basic-geometry/cotes-number.h delete mode 100644 basic-geometry/tangent-pair.c delete mode 100644 basic-geometry/tangent-pair.h diff --git a/basic-geometry-dev/main.c b/basic-geometry-dev/main.c index 0f4ad34..901b4e3 100644 --- a/basic-geometry-dev/main.c +++ b/basic-geometry-dev/main.c @@ -79,7 +79,7 @@ void list_work(const uint_fast32_t amount, structure_fp32_t* list) } } } - +/* int main() { const unsigned int amount = 1000000; @@ -121,3 +121,34 @@ int main() return 0; } +*/ + +/* +int main() { + BgcComplexFP32 complex, exponent, result; + + bgc_complex_set_values_fp32(0, 1, &complex); + + bgc_complex_set_values_fp32(4, 0, &exponent); + + bgc_complex_get_exponation_fp32(&complex, exponent.real, exponent.imaginary, &result); + + printf("(%f, %f) ^ (%f, %f) = (%f, %f)\n", complex.real, complex.imaginary, exponent.real, exponent.imaginary, result.real, result.imaginary); + + return 0; +} +*/ + +int main() { + const float exponent = 2.0f; + + BgcVersorFP32 turn, result; + + bgc_versor_set_turn_fp32(0, 0, 1, 120, BGC_ANGLE_UNIT_DEGREES, &turn); + + bgc_versor_get_exponation_fp32(&turn, exponent, &result); + + printf("(%f, %f, %f, %f) ^ %f = (%f, %f, %f, %f)\n", turn.s0, turn.x1, turn.x2, turn.x3, exponent, result.s0, result.x1, result.x2, result.x3); + + return 0; +} diff --git a/basic-geometry/basic-geometry.cbp b/basic-geometry/basic-geometry.cbp index 3e21644..1dadfea 100644 --- a/basic-geometry/basic-geometry.cbp +++ b/basic-geometry/basic-geometry.cbp @@ -48,6 +48,14 @@ + + + + + + @@ -76,10 +84,6 @@ - - - diff --git a/basic-geometry/basic-geometry.h b/basic-geometry/basic-geometry.h index 5a3923c..fb83f61 100644 --- a/basic-geometry/basic-geometry.h +++ b/basic-geometry/basic-geometry.h @@ -1,24 +1,25 @@ #ifndef _BGC_H_ #define _BGC_H_ -#include "utilities.h" +#include "./utilities.h" -#include "angle.h" +#include "./angle.h" -#include "vector2.h" -#include "vector3.h" +#include "./vector2.h" +#include "./vector3.h" -#include "matrixes.h" -#include "matrix2x2.h" -#include "matrix2x3.h" -#include "matrix3x2.h" -#include "matrix3x3.h" +#include "./matrixes.h" +#include "./matrix2x2.h" +#include "./matrix2x3.h" +#include "./matrix3x2.h" +#include "./matrix3x3.h" + +#include "./complex.h" +#include "./cotes-number.h" -#include "tangent-pair.h" +#include "./rotation3.h" -#include "rotation3.h" - -#include "quaternion.h" -#include "versor.h" +#include "./quaternion.h" +#include "./versor.h" #endif diff --git a/basic-geometry/basic-geometry.vcxproj b/basic-geometry/basic-geometry.vcxproj index 98620b5..6c60d06 100644 --- a/basic-geometry/basic-geometry.vcxproj +++ b/basic-geometry/basic-geometry.vcxproj @@ -21,6 +21,8 @@ + + @@ -28,7 +30,6 @@ - @@ -36,6 +37,8 @@ + + @@ -44,7 +47,7 @@ - + diff --git a/basic-geometry/basic-geometry.vcxproj.filters b/basic-geometry/basic-geometry.vcxproj.filters index 2349250..260e3e3 100644 --- a/basic-geometry/basic-geometry.vcxproj.filters +++ b/basic-geometry/basic-geometry.vcxproj.filters @@ -18,6 +18,12 @@ Файлы заголовков + + Файлы заголовков + + + Файлы заголовков + Файлы заголовков @@ -54,14 +60,17 @@ Файлы заголовков - - Файлы заголовков - Исходные файлы + + Исходные файлы + + + Исходные файлы + Исходные файлы @@ -95,8 +104,5 @@ Исходные файлы - - Исходные файлы - \ No newline at end of file diff --git a/basic-geometry/complex.c b/basic-geometry/complex.c new file mode 100644 index 0000000..59c6979 --- /dev/null +++ b/basic-geometry/complex.c @@ -0,0 +1,124 @@ +#include "./complex.h" + +extern inline void bgc_complex_reset_fp32(BgcComplexFP32* complex); +extern inline void bgc_complex_reset_fp64(BgcComplexFP64* complex); + +extern inline void bgc_complex_set_values_fp32(const float real, const float imaginary, BgcComplexFP32* destination); +extern inline void bgc_complex_set_values_fp64(const double real, const double imaginary, BgcComplexFP64* destination); + +extern inline float bgc_complex_get_square_modulus_fp32(const BgcComplexFP32* number); +extern inline double bgc_complex_get_square_modulus_fp64(const BgcComplexFP64* number); + +extern inline float bgc_complex_get_modulus_fp32(const BgcComplexFP32* number); +extern inline double bgc_complex_get_modulus_fp64(const BgcComplexFP64* number); + +extern inline int bgc_complex_is_zero_fp32(const BgcComplexFP32* number); +extern inline int bgc_complex_is_zero_fp64(const BgcComplexFP64* number); + +extern inline int bgc_complex_is_unit_fp32(const BgcComplexFP32* number); +extern inline int bgc_complex_is_unit_fp64(const BgcComplexFP64* number); + +extern inline void bgc_complex_copy_fp32(const BgcComplexFP32* source, BgcComplexFP32* destination); +extern inline void bgc_complex_copy_fp64(const BgcComplexFP64* source, BgcComplexFP64* destination); + +extern inline void bgc_complex_swap_fp32(BgcComplexFP32* number1, BgcComplexFP32* number2); +extern inline void bgc_complex_swap_fp64(BgcComplexFP64* number1, BgcComplexFP64* number2); + +extern inline void bgc_complex_convert_fp64_to_fp32(const BgcComplexFP64* source, BgcComplexFP32* destination); +extern inline void bgc_complex_convert_fp32_to_fp64(const BgcComplexFP32* source, BgcComplexFP64* destination); + +extern inline void bgc_complex_reverse_fp32(const BgcComplexFP32* number, BgcComplexFP32* reverse); +extern inline void bgc_complex_reverse_fp64(const BgcComplexFP64* number, BgcComplexFP64* reverse); + +extern inline int bgc_complex_normalize_fp32(const BgcComplexFP32* number, BgcComplexFP32* normalized); +extern inline int bgc_complex_normalize_fp64(const BgcComplexFP64* number, BgcComplexFP64* normalized); + +extern inline void bgc_complex_conjugate_fp32(const BgcComplexFP32* number, BgcComplexFP32* conjugate); +extern inline void bgc_complex_conjugate_fp64(const BgcComplexFP64* number, BgcComplexFP64* conjugate); + +extern inline int bgc_complex_invert_fp32(const BgcComplexFP32* number, BgcComplexFP32* inverted); +extern inline int bgc_complex_invert_fp64(const BgcComplexFP64* number, BgcComplexFP64* inverted); + +extern inline void bgc_complex_get_product_fp32(const BgcComplexFP32* number1, const BgcComplexFP32* number2, BgcComplexFP32* result); +extern inline void bgc_complex_get_product_fp64(const BgcComplexFP64* number1, const BgcComplexFP64* number2, BgcComplexFP64* result); + +extern inline int bgc_complex_get_ratio_fp32(const BgcComplexFP32* divident, const BgcComplexFP32* divisor, BgcComplexFP32* quotient); +extern inline int bgc_complex_get_ratio_fp64(const BgcComplexFP64* divident, const BgcComplexFP64* divisor, BgcComplexFP64* quotient); + +extern inline void bgc_complex_add_fp32(const BgcComplexFP32* number1, const BgcComplexFP32* number2, BgcComplexFP32* sum); +extern inline void bgc_complex_add_fp64(const BgcComplexFP64* number1, const BgcComplexFP64* number2, BgcComplexFP64* sum); + +extern inline void bgc_complex_add_scaled_fp32(const BgcComplexFP32* basic_number, const BgcComplexFP32* scalable_number, const float scale, BgcComplexFP32* sum); +extern inline void bgc_complex_add_scaled_fp64(const BgcComplexFP64* basic_number, const BgcComplexFP64* scalable_number, const double scale, BgcComplexFP64* sum); + +extern inline void bgc_complex_subtract_fp32(const BgcComplexFP32* minuend, const BgcComplexFP32* subtrahend, BgcComplexFP32* difference); +extern inline void bgc_complex_subtract_fp64(const BgcComplexFP64* minuend, const BgcComplexFP64* subtrahend, BgcComplexFP64* difference); + +extern inline void bgc_complex_subtract_scaled_fp32(const BgcComplexFP32* basic_number, const BgcComplexFP32* scalable_number, const float scale, BgcComplexFP32* difference); +extern inline void bgc_complex_subtract_scaled_fp64(const BgcComplexFP64* basic_number, const BgcComplexFP64* scalable_number, const double scale, BgcComplexFP64* difference); + +extern inline void bgc_complex_multiply_fp32(const BgcComplexFP32* multiplicand, const float multiplier, BgcComplexFP32* product); +extern inline void bgc_complex_multiply_fp64(const BgcComplexFP64* multiplicand, const double multiplier, BgcComplexFP64* product); + +extern inline void bgc_complex_divide_fp32(const BgcComplexFP32* dividend, const float divisor, BgcComplexFP32* quotient); +extern inline void bgc_complex_divide_fp64(const BgcComplexFP64* dividend, const double divisor, BgcComplexFP64* quotient); + +extern inline void bgc_complex_get_mean_of_two_fp32(const BgcComplexFP32* number1, const BgcComplexFP32* number2, BgcComplexFP32* mean); +extern inline void bgc_complex_get_mean_of_two_fp64(const BgcComplexFP64* number1, const BgcComplexFP64* number2, BgcComplexFP64* mean); + +extern inline void bgc_complex_get_mean_of_three_fp32(const BgcComplexFP32* number1, const BgcComplexFP32* number2, const BgcComplexFP32* number3, BgcComplexFP32* mean); +extern inline void bgc_complex_get_mean_of_three_fp64(const BgcComplexFP64* number1, const BgcComplexFP64* number2, const BgcComplexFP64* number3, BgcComplexFP64* mean); + +extern inline void bgc_complex_get_linear_interpolation_fp32(const BgcComplexFP32* number1, const BgcComplexFP32* number2, const float phase, BgcComplexFP32* interpolation); +extern inline void bgc_complex_get_linear_interpolation_fp64(const BgcComplexFP64* number1, const BgcComplexFP64* number2, const double phase, BgcComplexFP64* interpolation); + +extern inline void bgc_complex_minimize_fp32(const BgcComplexFP32* number, BgcComplexFP32* minimal); +extern inline void bgc_complex_minimize_fp64(const BgcComplexFP64* number, BgcComplexFP64* minimal); + +extern inline void bgc_complex_maximize_fp32(const BgcComplexFP32* number, BgcComplexFP32* maximal); +extern inline void bgc_complex_maximize_fp64(const BgcComplexFP64* number, BgcComplexFP64* maximal); + +extern inline int bgc_complex_are_close_fp32(const BgcComplexFP32* number1, const BgcComplexFP32* number2); +extern inline int bgc_complex_are_close_fp64(const BgcComplexFP64* number1, const BgcComplexFP64* number2); + +// =============== Get Exponation =============== // + +void bgc_complex_get_exponation_fp32(const BgcComplexFP32* base, const float real_exponent, const float imaginary_exponent, BgcComplexFP32* power) +{ + const float square_modulus = bgc_complex_get_square_modulus_fp32(base); + + if (square_modulus <= BGC_SQUARE_EPSYLON_FP32) { + power->real = 0.0f; + power->imaginary = 0.0f; + return; + } + + const float log_modulus = logf(square_modulus) * 0.5f; + const float angle = atan2f(base->imaginary, base->real); + + const float power_modulus = expf(real_exponent * log_modulus - imaginary_exponent * angle); + const float power_angle = real_exponent * angle + imaginary_exponent * log_modulus; + + power->real = power_modulus * cosf(power_angle); + power->imaginary = power_modulus * sinf(power_angle); +} + +void bgc_complex_get_exponation_fp64(const BgcComplexFP64* base, const double real_exponent, const double imaginary_exponent, BgcComplexFP64* power) +{ + const double square_modulus = bgc_complex_get_square_modulus_fp64(base); + + if (square_modulus <= BGC_SQUARE_EPSYLON_FP64) { + power->real = 0.0; + power->imaginary = 0.0; + return; + } + + const double log_modulus = log(square_modulus) * 0.5; + const double angle = atan2(base->imaginary, base->real); + + const double power_modulus = exp(real_exponent * log_modulus - imaginary_exponent * angle); + const double power_angle = real_exponent * angle + imaginary_exponent * log_modulus; + + power->real = power_modulus * cos(power_angle); + power->imaginary = power_modulus * sin(power_angle); +} diff --git a/basic-geometry/complex.h b/basic-geometry/complex.h new file mode 100644 index 0000000..c7b77ff --- /dev/null +++ b/basic-geometry/complex.h @@ -0,0 +1,531 @@ +#ifndef _BGC_COMPLEX_H_ +#define _BGC_COMPLEX_H_ + +#include "utilities.h" +#include "angle.h" + +#include + +typedef struct +{ + float real, imaginary; +} BgcComplexFP32; + +typedef struct +{ + double real, imaginary; +} BgcComplexFP64; + +// =================== Reset ==================== // + +inline void bgc_complex_reset_fp32(BgcComplexFP32* complex) +{ + complex->real = 0.0f; + complex->imaginary = 0.0f; +} + +inline void bgc_complex_reset_fp64(BgcComplexFP64* complex) +{ + complex->real = 0.0; + complex->imaginary = 0.0; +} + +// ==================== Set ===================== // + +inline void bgc_complex_set_values_fp32(const float real, const float imaginary, BgcComplexFP32* destination) +{ + destination->real = real; + destination->imaginary = imaginary; +} + +inline void bgc_complex_set_values_fp64(const double real, const double imaginary, BgcComplexFP64* destination) +{ + destination->real = real; + destination->imaginary = imaginary; +} + +// ================== Modulus =================== // + +inline float bgc_complex_get_square_modulus_fp32(const BgcComplexFP32* number) +{ + return number->real * number->real + number->imaginary * number->imaginary; +} + +inline double bgc_complex_get_square_modulus_fp64(const BgcComplexFP64* number) +{ + return number->real * number->real + number->imaginary * number->imaginary; +} + +inline float bgc_complex_get_modulus_fp32(const BgcComplexFP32* number) +{ + return sqrtf(bgc_complex_get_square_modulus_fp32(number)); +} + +inline double bgc_complex_get_modulus_fp64(const BgcComplexFP64* number) +{ + return sqrt(bgc_complex_get_square_modulus_fp64(number)); +} + +// ================= Comparison ================= // + +inline int bgc_complex_is_zero_fp32(const BgcComplexFP32* number) +{ + return bgc_complex_get_square_modulus_fp32(number) <= BGC_SQUARE_EPSYLON_FP32; +} + +inline int bgc_complex_is_zero_fp64(const BgcComplexFP64* number) +{ + return bgc_complex_get_square_modulus_fp64(number) <= BGC_SQUARE_EPSYLON_FP64; +} + +inline int bgc_complex_is_unit_fp32(const BgcComplexFP32* number) +{ + return bgc_is_sqare_unit_fp32(bgc_complex_get_square_modulus_fp32(number)); +} + +inline int bgc_complex_is_unit_fp64(const BgcComplexFP64* number) +{ + return bgc_is_sqare_unit_fp64(bgc_complex_get_square_modulus_fp64(number)); +} + +// ==================== Copy ==================== // + +inline void bgc_complex_copy_fp32(const BgcComplexFP32* source, BgcComplexFP32* destination) +{ + destination->real = source->real; + destination->imaginary = source->imaginary; +} + +inline void bgc_complex_copy_fp64(const BgcComplexFP64* source, BgcComplexFP64* destination) +{ + destination->real = source->real; + destination->imaginary = source->imaginary; +} + +// ==================== Swap ==================== // + +inline void bgc_complex_swap_fp32(BgcComplexFP32* number1, BgcComplexFP32* number2) +{ + const float real = number2->real; + const float imaginary = number2->imaginary; + + number2->real = number1->real; + number2->imaginary = number1->imaginary; + + number1->real = real; + number1->imaginary = imaginary; +} + +inline void bgc_complex_swap_fp64(BgcComplexFP64* number1, BgcComplexFP64* number2) +{ + const double real = number2->real; + const double imaginary = number2->imaginary; + + number2->real = number1->real; + number2->imaginary = number1->imaginary; + + number1->real = real; + number1->imaginary = imaginary; +} + +// ================== Convert =================== // + +inline void bgc_complex_convert_fp64_to_fp32(const BgcComplexFP64* source, BgcComplexFP32* destination) +{ + destination->real = (float)source->real; + destination->imaginary = (float)source->imaginary; +} + +inline void bgc_complex_convert_fp32_to_fp64(const BgcComplexFP32* source, BgcComplexFP64* destination) +{ + destination->real = source->real; + destination->imaginary = source->imaginary; +} + +// ================== Reverse =================== // + +inline void bgc_complex_reverse_fp32(const BgcComplexFP32* number, BgcComplexFP32* reverse) +{ + reverse->real = -number->real; + reverse->imaginary = -number->imaginary; +} + +inline void bgc_complex_reverse_fp64(const BgcComplexFP64* number, BgcComplexFP64* reverse) +{ + reverse->real = -number->real; + reverse->imaginary = -number->imaginary; +} + +// ================= Normalize ================== // + +inline int bgc_complex_normalize_fp32(const BgcComplexFP32* number, BgcComplexFP32* normalized) +{ + const float square_modulus = bgc_complex_get_square_modulus_fp32(number); + + if (bgc_is_sqare_unit_fp32(square_modulus)) { + normalized->real = number->real; + normalized->imaginary = number->imaginary; + return 1; + } + + if (square_modulus <= BGC_SQUARE_EPSYLON_FP32 || square_modulus != square_modulus) { + return 0; + } + + const float multiplicand = sqrtf(1.0f / square_modulus); + + normalized->real = number->real * multiplicand; + normalized->imaginary = number->imaginary * multiplicand; + + return 1; +} + +inline int bgc_complex_normalize_fp64(const BgcComplexFP64* number, BgcComplexFP64* normalized) +{ + const double square_modulus = bgc_complex_get_square_modulus_fp64(number); + + if (bgc_is_sqare_unit_fp64(square_modulus)) { + normalized->real = number->real; + normalized->imaginary = number->imaginary; + return 1; + } + + if (square_modulus <= BGC_SQUARE_EPSYLON_FP64 || square_modulus != square_modulus) { + return 0; + } + + const double multiplicand = sqrt(1.0 / square_modulus); + + normalized->real = number->real * multiplicand; + normalized->imaginary = number->imaginary * multiplicand; + + return 1; +} + +// ================= Conjugate ================== // + +inline void bgc_complex_conjugate_fp32(const BgcComplexFP32* number, BgcComplexFP32* conjugate) +{ + conjugate->real = number->real; + conjugate->imaginary = -number->imaginary; +} + +inline void bgc_complex_conjugate_fp64(const BgcComplexFP64* number, BgcComplexFP64* conjugate) +{ + conjugate->real = number->real; + conjugate->imaginary = -number->imaginary; +} + +// =================== Invert =================== // + +inline int bgc_complex_invert_fp32(const BgcComplexFP32* number, BgcComplexFP32* inverted) +{ + const float square_modulus = bgc_complex_get_square_modulus_fp32(number); + + if (square_modulus <= BGC_SQUARE_EPSYLON_FP32 || square_modulus != square_modulus) { + return 0; + } + + const float multiplicand = 1.0f / square_modulus; + + inverted->real = number->real * multiplicand; + inverted->imaginary = -number->imaginary * multiplicand; + + return 1; +} + +inline int bgc_complex_invert_fp64(const BgcComplexFP64* number, BgcComplexFP64* inverted) +{ + const double square_modulus = bgc_complex_get_square_modulus_fp64(number); + + if (square_modulus <= BGC_SQUARE_EPSYLON_FP64 || square_modulus != square_modulus) { + return 0; + } + + const double multiplicand = 1.0 / square_modulus; + + inverted->real = number->real * multiplicand; + inverted->imaginary = -number->imaginary * multiplicand; + + return 1; +} + +// ================ Get Product ================= // + +inline void bgc_complex_get_product_fp32(const BgcComplexFP32* number1, const BgcComplexFP32* number2, BgcComplexFP32* result) +{ + const float real = number1->real * number2->real - number1->imaginary * number2->imaginary; + const float imaginary = number1->real * number2->imaginary + number1->imaginary * number2->real; + + result->real = real; + result->imaginary = imaginary; +} + +inline void bgc_complex_get_product_fp64(const BgcComplexFP64* number1, const BgcComplexFP64* number2, BgcComplexFP64* result) +{ + const double real = number1->real * number2->real - number1->imaginary * number2->imaginary; + const double imaginary = number1->real * number2->imaginary + number1->imaginary * number2->real; + + result->real = real; + result->imaginary = imaginary; +} + +// ================= Get Ratio ================== // + +inline int bgc_complex_get_ratio_fp32(const BgcComplexFP32* divident, const BgcComplexFP32* divisor, BgcComplexFP32* quotient) +{ + const float square_modulus = bgc_complex_get_square_modulus_fp32(divisor); + + if (square_modulus <= BGC_SQUARE_EPSYLON_FP32) { + return 0; + } + + const float real = divident->real * divisor->real + divident->imaginary * divisor->imaginary; + const float imaginary = divident->imaginary * divisor->real - divident->real * divisor->imaginary; + + const float multiplier = 1.0f / square_modulus; + + quotient->real = real * multiplier; + quotient->imaginary = imaginary * multiplier; + + return 1; +} + +inline int bgc_complex_get_ratio_fp64(const BgcComplexFP64* divident, const BgcComplexFP64* divisor, BgcComplexFP64* quotient) +{ + const double square_modulus = bgc_complex_get_square_modulus_fp64(divisor); + + if (square_modulus <= BGC_SQUARE_EPSYLON_FP64) { + return 0; + } + + const double real = divident->real * divisor->real + divident->imaginary * divisor->imaginary; + const double imaginary = divident->imaginary * divisor->real - divident->real * divisor->imaginary; + + const double multiplier = 1.0 / square_modulus; + + quotient->real = real * multiplier; + quotient->imaginary = imaginary * multiplier; + + return 1; +} + +// =============== Get Exponation =============== // + +void bgc_complex_get_exponation_fp32(const BgcComplexFP32* base, const float real_exponent, const float imaginary_exponent, BgcComplexFP32* power); + +void bgc_complex_get_exponation_fp64(const BgcComplexFP64* base, const double real_exponent, const double imaginary_exponent, BgcComplexFP64* power); + +// ==================== Add ===================== // + +inline void bgc_complex_add_fp32(const BgcComplexFP32* number1, const BgcComplexFP32* number2, BgcComplexFP32* sum) +{ + sum->real = number1->real + number2->real; + sum->imaginary = number1->imaginary + number2->imaginary; +} + +inline void bgc_complex_add_fp64(const BgcComplexFP64* number1, const BgcComplexFP64* number2, BgcComplexFP64* sum) +{ + sum->real = number1->real + number2->real; + sum->imaginary = number1->imaginary + number2->imaginary; +} + +// ================= Add scaled ================= // + +inline void bgc_complex_add_scaled_fp32(const BgcComplexFP32* basic_number, const BgcComplexFP32* scalable_number, const float scale, BgcComplexFP32* sum) +{ + sum->real = basic_number->real + scalable_number->real * scale; + sum->imaginary = basic_number->imaginary + scalable_number->imaginary * scale; +} + +inline void bgc_complex_add_scaled_fp64(const BgcComplexFP64* basic_number, const BgcComplexFP64* scalable_number, const double scale, BgcComplexFP64* sum) +{ + sum->real = basic_number->real + scalable_number->real * scale; + sum->imaginary = basic_number->imaginary + scalable_number->imaginary * scale; +} + +// ================== Subtract ================== // + +inline void bgc_complex_subtract_fp32(const BgcComplexFP32* minuend, const BgcComplexFP32* subtrahend, BgcComplexFP32* difference) +{ + difference->real = minuend->real - subtrahend->real; + difference->imaginary = minuend->imaginary - subtrahend->imaginary; +} + +inline void bgc_complex_subtract_fp64(const BgcComplexFP64* minuend, const BgcComplexFP64* subtrahend, BgcComplexFP64* difference) +{ + difference->real = minuend->real - subtrahend->real; + difference->imaginary = minuend->imaginary - subtrahend->imaginary; +} + +// ============== Subtract scaled =============== // + +inline void bgc_complex_subtract_scaled_fp32(const BgcComplexFP32* basic_number, const BgcComplexFP32* scalable_number, const float scale, BgcComplexFP32* difference) +{ + difference->real = basic_number->real - scalable_number->real * scale; + difference->imaginary = basic_number->imaginary - scalable_number->imaginary * scale; +} + +inline void bgc_complex_subtract_scaled_fp64(const BgcComplexFP64* basic_number, const BgcComplexFP64* scalable_number, const double scale, BgcComplexFP64* difference) +{ + difference->real = basic_number->real - scalable_number->real * scale; + difference->imaginary = basic_number->imaginary - scalable_number->imaginary * scale; +} + +// ================== Multiply ================== // + +inline void bgc_complex_multiply_fp32(const BgcComplexFP32* multiplicand, const float multiplier, BgcComplexFP32* product) +{ + product->real = multiplicand->real * multiplier; + product->imaginary = multiplicand->imaginary * multiplier; +} + +inline void bgc_complex_multiply_fp64(const BgcComplexFP64* multiplicand, const double multiplier, BgcComplexFP64* product) +{ + product->real = multiplicand->real * multiplier; + product->imaginary = multiplicand->imaginary * multiplier; +} + +// =================== Divide =================== // + +inline void bgc_complex_divide_fp32(const BgcComplexFP32* dividend, const float divisor, BgcComplexFP32* quotient) +{ + bgc_complex_multiply_fp32(dividend, 1.0f / divisor, quotient); +} + +inline void bgc_complex_divide_fp64(const BgcComplexFP64* dividend, const double divisor, BgcComplexFP64* quotient) +{ + bgc_complex_multiply_fp64(dividend, 1.0 / divisor, quotient); +} + +// ================== Average2 ================== // + +inline void bgc_complex_get_mean_of_two_fp32(const BgcComplexFP32* number1, const BgcComplexFP32* number2, BgcComplexFP32* mean) +{ + mean->real = (number1->real + number2->real) * 0.5f; + mean->imaginary = (number1->imaginary + number2->imaginary) * 0.5f; +} + +inline void bgc_complex_get_mean_of_two_fp64(const BgcComplexFP64* number1, const BgcComplexFP64* number2, BgcComplexFP64* mean) +{ + mean->real = (number1->real + number2->real) * 0.5; + mean->imaginary = (number1->imaginary + number2->imaginary) * 0.5; +} + +// ================== Average3 ================== // + +inline void bgc_complex_get_mean_of_three_fp32(const BgcComplexFP32* number1, const BgcComplexFP32* number2, const BgcComplexFP32* number3, BgcComplexFP32* mean) +{ + mean->real = (number1->real + number2->real + number3->real) * BGC_ONE_THIRD_FP32; + mean->imaginary = (number1->imaginary + number2->imaginary + number3->imaginary) * BGC_ONE_THIRD_FP32; +} + +inline void bgc_complex_get_mean_of_three_fp64(const BgcComplexFP64* number1, const BgcComplexFP64* number2, const BgcComplexFP64* number3, BgcComplexFP64* mean) +{ + mean->real = (number1->real + number2->real + number3->real) * BGC_ONE_THIRD_FP64; + mean->imaginary = (number1->imaginary + number2->imaginary + number3->imaginary) * BGC_ONE_THIRD_FP64; +} + +// =================== Linear =================== // + +inline void bgc_complex_get_linear_interpolation_fp32(const BgcComplexFP32* number1, const BgcComplexFP32* number2, const float phase, BgcComplexFP32* interpolation) +{ + const float counterphase = 1.0f - phase; + + interpolation->real = number1->real * counterphase + number2->real * phase; + interpolation->imaginary = number1->imaginary * counterphase + number2->imaginary * phase; +} + +inline void bgc_complex_get_linear_interpolation_fp64(const BgcComplexFP64* number1, const BgcComplexFP64* number2, const double phase, BgcComplexFP64* interpolation) +{ + const double counterphase = 1.0 - phase; + + interpolation->real = number1->real * counterphase + number2->real * phase; + interpolation->imaginary = number1->imaginary * counterphase + number2->imaginary * phase; +} + +// ================== Minimal =================== // + +inline void bgc_complex_minimize_fp32(const BgcComplexFP32* number, BgcComplexFP32* minimal) +{ + if (number->real < minimal->real) { + minimal->real = number->real; + } + + if (number->imaginary < minimal->imaginary) { + minimal->imaginary = number->imaginary; + } +} + +inline void bgc_complex_minimize_fp64(const BgcComplexFP64* number, BgcComplexFP64* minimal) +{ + if (number->real < minimal->real) { + minimal->real = number->real; + } + + if (number->imaginary < minimal->imaginary) { + minimal->imaginary = number->imaginary; + } +} + +// ================== Maximal =================== // + +inline void bgc_complex_maximize_fp32(const BgcComplexFP32* number, BgcComplexFP32* maximal) +{ + if (number->real > maximal->real) { + maximal->real = number->real; + } + + if (number->imaginary > maximal->imaginary) { + maximal->imaginary = number->imaginary; + } +} + +inline void bgc_complex_maximize_fp64(const BgcComplexFP64* number, BgcComplexFP64* maximal) +{ + if (number->real > maximal->real) { + maximal->real = number->real; + } + + if (number->imaginary > maximal->imaginary) { + maximal->imaginary = number->imaginary; + } +} + +// ================== Are Close ================= // + +inline int bgc_complex_are_close_fp32(const BgcComplexFP32* number1, const BgcComplexFP32* number2) +{ + const float square_modulus1 = bgc_complex_get_square_modulus_fp32(number1); + const float square_modulus2 = bgc_complex_get_square_modulus_fp32(number2); + + const float d_real = number1->real - number2->real; + const float d_imaginary = number1->imaginary - number2->imaginary; + + const float square_distance = d_real * d_real + d_imaginary * d_imaginary; + + if (square_modulus1 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32 || square_modulus2 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP32) { + return square_distance <= BGC_SQUARE_EPSYLON_FP32; + } + + return square_distance <= BGC_SQUARE_EPSYLON_FP32 * square_modulus1 && square_distance <= BGC_SQUARE_EPSYLON_FP32 * square_modulus2; +} + +inline int bgc_complex_are_close_fp64(const BgcComplexFP64* number1, const BgcComplexFP64* number2) +{ + const double square_modulus1 = bgc_complex_get_square_modulus_fp64(number1); + const double square_modulus2 = bgc_complex_get_square_modulus_fp64(number2); + + const double d_real = number1->real - number2->real; + const double d_imaginary = number1->imaginary - number2->imaginary; + + const double square_distance = d_real * d_real + d_imaginary * d_imaginary; + + if (square_modulus1 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64 || square_modulus2 <= BGC_EPSYLON_EFFECTIVENESS_LIMIT_FP64) { + return square_distance <= BGC_SQUARE_EPSYLON_FP64; + } + + return square_distance <= BGC_SQUARE_EPSYLON_FP32 * square_modulus1 && square_distance <= BGC_SQUARE_EPSYLON_FP32 * square_modulus2; +} + +#endif diff --git a/basic-geometry/cotes-number.c b/basic-geometry/cotes-number.c new file mode 100644 index 0000000..fc7cc57 --- /dev/null +++ b/basic-geometry/cotes-number.c @@ -0,0 +1,82 @@ +#include "./cotes-number.h" + +const BgcCotesNumberFP32 BGC_IDLE_COTES_NUMBER_FP32 = { 1.0f, 0.0f }; + +const BgcCotesNumberFP64 BGC_IDLE_COTES_NUMBER_FP64 = { 1.0, 0.0 }; + +extern inline void bgc_cotes_number_reset_fp32(BgcCotesNumberFP32* number); +extern inline void bgc_cotes_number_reset_fp64(BgcCotesNumberFP64* number); + +extern inline void bgc_cotes_number_set_values_fp32(const float x1, const float x2, BgcCotesNumberFP32* number); +extern inline void bgc_cotes_number_set_values_fp64(const double x1, const double x2, BgcCotesNumberFP64* number); + +extern inline void bgc_cotes_number_set_turn_fp32(const float angle, const BgcAngleUnitEnum unit, BgcCotesNumberFP32* number); +extern inline void bgc_cotes_number_set_turn_fp64(const double angle, const BgcAngleUnitEnum unit, BgcCotesNumberFP64* number); + +extern inline float bgc_cotes_number_get_angle_fp32(const BgcCotesNumberFP32* number, const BgcAngleUnitEnum unit); +extern inline double bgc_cotes_number_get_angle_fp64(const BgcCotesNumberFP64* number, const BgcAngleUnitEnum unit); + +extern inline void bgc_cotes_number_copy_fp32(const BgcCotesNumberFP32* source, BgcCotesNumberFP32* destination); +extern inline void bgc_cotes_number_copy_fp64(const BgcCotesNumberFP64* source, BgcCotesNumberFP64* destination); + +extern inline void bgc_cotes_number_swap_fp32(BgcCotesNumberFP32* number1, BgcCotesNumberFP32* number2); +extern inline void bgc_cotes_number_swap_fp64(BgcCotesNumberFP64* number1, BgcCotesNumberFP64* number2); + +extern inline void bgc_cotes_number_convert_fp64_to_fp32(const BgcCotesNumberFP64* source, BgcCotesNumberFP32* destination); +extern inline void bgc_cotes_number_convert_fp32_to_fp64(const BgcCotesNumberFP32* source, BgcCotesNumberFP64* destination); + +extern inline void bgc_cotes_number_invert_fp32(const BgcCotesNumberFP32* number, BgcCotesNumberFP32* inverted); +extern inline void bgc_cotes_number_invert_fp64(const BgcCotesNumberFP64* number, BgcCotesNumberFP64* inverted); + +extern inline void bgc_cotes_number_get_exponation_fp32(const BgcCotesNumberFP32* base, const float exponent, BgcCotesNumberFP32* power); +extern inline void bgc_cotes_number_get_exponation_fp64(const BgcCotesNumberFP64* base, const double exponent, BgcCotesNumberFP64* power); + +extern inline void bgc_cotes_number_combine_fp32(const BgcCotesNumberFP32* number1, const BgcCotesNumberFP32* number2, BgcCotesNumberFP32* result); +extern inline void bgc_cotes_number_combine_fp64(const BgcCotesNumberFP64* number1, const BgcCotesNumberFP64* number2, BgcCotesNumberFP64* result); + +extern inline void bgc_cotes_number_get_rotation_matrix_fp32(const BgcCotesNumberFP32* number, BgcMatrix2x2FP32* matrix); +extern inline void bgc_cotes_number_get_rotation_matrix_fp64(const BgcCotesNumberFP64* number, BgcMatrix2x2FP64* matrix); + +extern inline void bgc_cotes_number_get_reverse_matrix_fp32(const BgcCotesNumberFP32* number, BgcMatrix2x2FP32* matrix); +extern inline void bgc_cotes_number_get_reverse_matrix_fp64(const BgcCotesNumberFP64* number, BgcMatrix2x2FP64* matrix); + +extern inline void bgc_cotes_number_turn_vector_fp32(const BgcCotesNumberFP32* number, const BgcVector2FP32* vector, BgcVector2FP32* result); +extern inline void bgc_cotes_number_turn_vector_fp64(const BgcCotesNumberFP64* number, const BgcVector2FP64* vector, BgcVector2FP64* result); + +extern inline void bgc_cotes_number_turn_vector_back_fp32(const BgcCotesNumberFP32* number, const BgcVector2FP32* vector, BgcVector2FP32* result); +extern inline void bgc_cotes_number_turn_vector_back_fp64(const BgcCotesNumberFP64* number, const BgcVector2FP64* vector, BgcVector2FP64* result); + +extern inline int bgc_cotes_number_are_close_fp32(const BgcCotesNumberFP32* number1, const BgcCotesNumberFP32* number2); +extern inline int bgc_cotes_number_are_close_fp64(const BgcCotesNumberFP64* number1, const BgcCotesNumberFP64* number2); + +void _bgc_cotes_number_normalize_fp32(const float square_modulus, _BgcTwinCotesNumberFP32* twin) +{ + // (square_modulus != square_modulus) is true when square_modulus is NaN + + if (square_modulus <= BGC_SQUARE_EPSYLON_FP32 || square_modulus != square_modulus) { + twin->cos = 1.0f; + twin->sin = 0.0f; + return; + } + + const float multiplier = sqrtf(1.0f / square_modulus); + + twin->cos *= multiplier; + twin->sin *= multiplier; +} + +void _bgc_cotes_number_normalize_fp64(const double square_modulus, _BgcTwinCotesNumberFP64* twin) +{ + // (square_modulus != square_modulus) is true when square_modulus is NaN + + if (square_modulus <= BGC_SQUARE_EPSYLON_FP64 || square_modulus != square_modulus) { + twin->cos = 1.0; + twin->sin = 0.0; + return; + } + + const double multiplier = sqrt(1.0 / square_modulus); + + twin->cos *= multiplier; + twin->sin *= multiplier; +} diff --git a/basic-geometry/cotes-number.h b/basic-geometry/cotes-number.h new file mode 100644 index 0000000..e4944a6 --- /dev/null +++ b/basic-geometry/cotes-number.h @@ -0,0 +1,374 @@ +#ifndef _BGC_COTES_NUMBER_H_ +#define _BGC_COTES_NUMBER_H_ + +#include + +#include "utilities.h" +#include "angle.h" +#include "vector2.h" +#include "matrix2x2.h" + +// =================== Types ==================== // + +typedef struct +{ + const float cos, sin; +} BgcCotesNumberFP32; + +typedef struct +{ + const double cos, sin; +} BgcCotesNumberFP64; + +// ================= Dark Twins ================= // + +typedef struct { + float cos, sin; +} _BgcTwinCotesNumberFP32; + +typedef struct { + double cos, sin; +} _BgcTwinCotesNumberFP64; + +// ================= Constants ================== // + +extern const BgcCotesNumberFP32 BGC_IDLE_COTES_NUMBER_FP32; +extern const BgcCotesNumberFP64 BGC_IDLE_COTES_NUMBER_FP64; + +// =================== Reset ==================== // + +inline void bgc_cotes_number_reset_fp32(BgcCotesNumberFP32* number) +{ + _BgcTwinCotesNumberFP32* twin = (_BgcTwinCotesNumberFP32*)number; + + twin->cos = 1.0f; + twin->sin = 0.0f; +} + +inline void bgc_cotes_number_reset_fp64(BgcCotesNumberFP64* number) +{ + _BgcTwinCotesNumberFP64* twin = (_BgcTwinCotesNumberFP64*)number; + + twin->cos = 1.0; + twin->sin = 0.0; +} + +// ==================== Set ===================== // + +void _bgc_cotes_number_normalize_fp32(const float square_modulus, _BgcTwinCotesNumberFP32* twin); + +void _bgc_cotes_number_normalize_fp64(const double square_modulus, _BgcTwinCotesNumberFP64* twin); + +inline void bgc_cotes_number_set_values_fp32(const float x1, const float x2, BgcCotesNumberFP32* number) +{ + const float square_modulus = x1 * x1 + x2 * x2; + + _BgcTwinCotesNumberFP32* twin = (_BgcTwinCotesNumberFP32*)number; + + twin->cos = x1; + twin->sin = x2; + + if (!bgc_is_sqare_unit_fp32(square_modulus)) { + _bgc_cotes_number_normalize_fp32(square_modulus, twin); + } +} + +inline void bgc_cotes_number_set_values_fp64(const double x1, const double x2, BgcCotesNumberFP64* number) +{ + const double square_modulus = x1 * x1 + x2 * x2; + + _BgcTwinCotesNumberFP64* twin = (_BgcTwinCotesNumberFP64*)number; + + twin->cos = x1; + twin->sin = x2; + + if (!bgc_is_sqare_unit_fp64(square_modulus)) { + _bgc_cotes_number_normalize_fp64(square_modulus, twin); + } +} + +// ================== Set Turn ================== // + +inline void bgc_cotes_number_set_turn_fp32(const float angle, const BgcAngleUnitEnum unit, BgcCotesNumberFP32* number) +{ + const float radians = bgc_angle_to_radians_fp32(angle, unit); + + _BgcTwinCotesNumberFP32* twin = (_BgcTwinCotesNumberFP32*)number; + + twin->cos = cosf(radians); + twin->sin = sinf(radians); +} + +inline void bgc_cotes_number_set_turn_fp64(const double angle, const BgcAngleUnitEnum unit, BgcCotesNumberFP64* number) +{ + const double radians = bgc_angle_to_radians_fp64(angle, unit); + + _BgcTwinCotesNumberFP64* twin = (_BgcTwinCotesNumberFP64*)number; + + twin->cos = cos(radians); + twin->sin = sin(radians); +} + +// =================== Angle =================== // + +inline float bgc_cotes_number_get_angle_fp32(const BgcCotesNumberFP32* number, const BgcAngleUnitEnum unit) +{ + if (number->cos >= 1.0f - BGC_EPSYLON_FP32) { + return 0.0f; + } + + if (number->cos <= -1.0f + BGC_EPSYLON_FP32) { + return bgc_angle_get_half_circle_fp32(unit); + } + + if (number->sin >= 1.0f - BGC_EPSYLON_FP32) { + return bgc_angle_get_quater_circle_fp32(unit); + } + + if (number->sin <= -1.0f + BGC_EPSYLON_FP32) { + return 0.75f * bgc_angle_get_full_circle_fp32(unit); + } + + return bgc_radians_to_units_fp32(atan2f(number->sin, number->cos), unit); +} + +inline double bgc_cotes_number_get_angle_fp64(const BgcCotesNumberFP64* number, const BgcAngleUnitEnum unit) +{ + if (number->cos >= 1.0 - BGC_EPSYLON_FP64) { + return 0.0; + } + + if (number->cos <= -1.0 + BGC_EPSYLON_FP64) { + return bgc_angle_get_half_circle_fp64(unit); + } + + if (number->sin >= 1.0 - BGC_EPSYLON_FP64) { + return bgc_angle_get_quater_circle_fp64(unit); + } + + if (number->sin <= -1.0 + BGC_EPSYLON_FP64) { + return 0.75 * bgc_angle_get_full_circle_fp64(unit); + } + + return bgc_radians_to_units_fp64(atan2(number->sin, number->cos), unit); +} + +// ==================== Copy ==================== // + +inline void bgc_cotes_number_copy_fp32(const BgcCotesNumberFP32* source, BgcCotesNumberFP32* destination) +{ + _BgcTwinCotesNumberFP32* twin = (_BgcTwinCotesNumberFP32*)destination; + + twin->cos = source->cos; + twin->sin = source->sin; +} + +inline void bgc_cotes_number_copy_fp64(const BgcCotesNumberFP64* source, BgcCotesNumberFP64* destination) +{ + _BgcTwinCotesNumberFP64* twin = (_BgcTwinCotesNumberFP64*)destination; + + twin->cos = source->cos; + twin->sin = source->sin; +} + +// ==================== Swap ==================== // + +inline void bgc_cotes_number_swap_fp32(BgcCotesNumberFP32* number1, BgcCotesNumberFP32* number2) +{ + const float cos = number1->cos; + const float sin = number1->sin; + + _BgcTwinCotesNumberFP32* twin1 = (_BgcTwinCotesNumberFP32*)number1; + + twin1->cos = number2->cos; + twin1->sin = number2->sin; + + _BgcTwinCotesNumberFP32* twin2 = (_BgcTwinCotesNumberFP32*)number2; + + twin2->cos = cos; + twin2->sin = sin; +} + +inline void bgc_cotes_number_swap_fp64(BgcCotesNumberFP64* number1, BgcCotesNumberFP64* number2) +{ + const double cos = number1->cos; + const double sin = number1->sin; + + _BgcTwinCotesNumberFP64* twin1 = (_BgcTwinCotesNumberFP64*)number1; + + twin1->cos = number2->cos; + twin1->sin = number2->sin; + + _BgcTwinCotesNumberFP64* twin2 = (_BgcTwinCotesNumberFP64*)number2; + + twin2->cos = cos; + twin2->sin = sin; +} + +// ================== Convert =================== // + +inline void bgc_cotes_number_convert_fp64_to_fp32(const BgcCotesNumberFP64* source, BgcCotesNumberFP32* destination) +{ + bgc_cotes_number_set_values_fp32((float)source->cos, (float)source->sin, destination); +} + +inline void bgc_cotes_number_convert_fp32_to_fp64(const BgcCotesNumberFP32* source, BgcCotesNumberFP64* destination) +{ + bgc_cotes_number_set_values_fp64((double)source->cos, (double)source->sin, destination); +} + +// =================== Invert =================== // + +inline void bgc_cotes_number_invert_fp32(const BgcCotesNumberFP32* number, BgcCotesNumberFP32* inverted) +{ + _BgcTwinCotesNumberFP32* twin = (_BgcTwinCotesNumberFP32*)inverted; + + twin->cos = number->cos; + twin->sin = -number->sin; +} + +inline void bgc_cotes_number_invert_fp64(const BgcCotesNumberFP64* number, BgcCotesNumberFP64* inverted) +{ + _BgcTwinCotesNumberFP64* twin = (_BgcTwinCotesNumberFP64*)inverted; + + twin->cos = number->cos; + twin->sin = -number->sin; +} + +// ================= Exponation ================= // + +inline void bgc_cotes_number_get_exponation_fp32(const BgcCotesNumberFP32* base, const float exponent, BgcCotesNumberFP32* power) +{ + const float power_angle = exponent * atan2f(base->sin, base->cos); + + _BgcTwinCotesNumberFP32* twin = (_BgcTwinCotesNumberFP32*)power; + + twin->cos = cosf(power_angle); + twin->sin = sinf(power_angle); +} + +inline void bgc_cotes_number_get_exponation_fp64(const BgcCotesNumberFP64* base, const double exponent, BgcCotesNumberFP64* power) +{ + const double power_angle = exponent * atan2(base->sin, base->cos); + + _BgcTwinCotesNumberFP64* twin = (_BgcTwinCotesNumberFP64*)power; + + twin->cos = cos(power_angle); + twin->sin = sin(power_angle); +} + +// ================ Combination ================= // + +inline void bgc_cotes_number_combine_fp32(const BgcCotesNumberFP32* number1, const BgcCotesNumberFP32* number2, BgcCotesNumberFP32* result) +{ + bgc_cotes_number_set_values_fp32( + number1->cos * number2->cos - number1->sin * number2->sin, + number1->cos * number2->sin + number1->sin * number2->cos, + result + ); +} + +inline void bgc_cotes_number_combine_fp64(const BgcCotesNumberFP64* number1, const BgcCotesNumberFP64* number2, BgcCotesNumberFP64* result) +{ + bgc_cotes_number_set_values_fp64( + number1->cos * number2->cos - number1->sin * number2->sin, + number1->cos * number2->sin + number1->sin * number2->cos, + result + ); +} + +// ============== Rotation Matrix =============== // + +inline void bgc_cotes_number_get_rotation_matrix_fp32(const BgcCotesNumberFP32* number, BgcMatrix2x2FP32* matrix) +{ + matrix->r1c1 = number->cos; + matrix->r1c2 = -number->sin; + matrix->r2c1 = number->sin; + matrix->r2c2 = number->cos; +} + +inline void bgc_cotes_number_get_rotation_matrix_fp64(const BgcCotesNumberFP64* number, BgcMatrix2x2FP64* matrix) +{ + matrix->r1c1 = number->cos; + matrix->r1c2 = -number->sin; + matrix->r2c1 = number->sin; + matrix->r2c2 = number->cos; +} + +// ============== Reverse Matrix ================ // + +inline void bgc_cotes_number_get_reverse_matrix_fp32(const BgcCotesNumberFP32* number, BgcMatrix2x2FP32* matrix) +{ + matrix->r1c1 = number->cos; + matrix->r1c2 = number->sin; + matrix->r2c1 = -number->sin; + matrix->r2c2 = number->cos; +} + +inline void bgc_cotes_number_get_reverse_matrix_fp64(const BgcCotesNumberFP64* number, BgcMatrix2x2FP64* matrix) +{ + matrix->r1c1 = number->cos; + matrix->r1c2 = number->sin; + matrix->r2c1 = -number->sin; + matrix->r2c2 = number->cos; +} + +// ================ Turn Vector ================= // + +inline void bgc_cotes_number_turn_vector_fp32(const BgcCotesNumberFP32* number, const BgcVector2FP32* vector, BgcVector2FP32* result) +{ + const float x1 = number->cos * vector->x1 - number->sin * vector->x2; + const float x2 = number->sin * vector->x1 + number->cos * vector->x2; + + result->x1 = x1; + result->x2 = x2; +} + +inline void bgc_cotes_number_turn_vector_fp64(const BgcCotesNumberFP64* number, const BgcVector2FP64* vector, BgcVector2FP64* result) +{ + const double x1 = number->cos * vector->x1 - number->sin * vector->x2; + const double x2 = number->sin * vector->x1 + number->cos * vector->x2; + + result->x1 = x1; + result->x2 = x2; +} + +// ============ Turn Vector Backward ============ // + +inline void bgc_cotes_number_turn_vector_back_fp32(const BgcCotesNumberFP32* number, const BgcVector2FP32* vector, BgcVector2FP32* result) +{ + const float x1 = number->sin * vector->x2 + number->cos * vector->x1; + const float x2 = number->cos * vector->x2 - number->sin * vector->x1; + + result->x1 = x1; + result->x2 = x2; +} + +inline void bgc_cotes_number_turn_vector_back_fp64(const BgcCotesNumberFP64* number, const BgcVector2FP64* vector, BgcVector2FP64* result) +{ + const double x1 = number->sin * vector->x2 + number->cos * vector->x1; + const double x2 = number->cos * vector->x2 - number->sin * vector->x1; + + result->x1 = x1; + result->x2 = x2; +} + +// ================== Are Close ================= // + +inline int bgc_cotes_number_are_close_fp32(const BgcCotesNumberFP32* number1, const BgcCotesNumberFP32* number2) +{ + const float d_cos = number1->cos - number2->cos; + const float d_sin = number1->sin - number2->sin; + + return d_cos * d_cos + d_sin * d_sin <= BGC_SQUARE_EPSYLON_FP32; +} + +inline int bgc_cotes_number_are_close_fp64(const BgcCotesNumberFP64* number1, const BgcCotesNumberFP64* number2) +{ + const double d_cos = number1->cos - number2->cos; + const double d_sin = number1->sin - number2->sin; + + return d_cos * d_cos + d_sin * d_sin <= BGC_SQUARE_EPSYLON_FP64; +} + +#endif diff --git a/basic-geometry/quaternion.c b/basic-geometry/quaternion.c index 6694803..963dba7 100644 --- a/basic-geometry/quaternion.c +++ b/basic-geometry/quaternion.c @@ -72,5 +72,9 @@ extern inline int bgc_quaternion_get_rotation_matrix_fp64(const BgcQuaternionFP6 extern inline int bgc_quaternion_get_reverse_matrix_fp32(const BgcQuaternionFP32* quaternion, BgcMatrix3x3FP32* reverse); extern inline int bgc_quaternion_get_reverse_matrix_fp64(const BgcQuaternionFP64* quaternion, BgcMatrix3x3FP64* reverse); +extern inline int bgc_quaternion_get_both_matrixes_fp32(const BgcQuaternionFP32* quaternion, BgcMatrix3x3FP32* rotation, BgcMatrix3x3FP32* reverse); +extern inline int bgc_quaternion_get_both_matrixes_fp64(const BgcQuaternionFP64* quaternion, BgcMatrix3x3FP64* rotation, BgcMatrix3x3FP64* reverse); + + extern inline int bgc_quaternion_are_close_fp32(const BgcQuaternionFP32* quaternion1, const BgcQuaternionFP32* quaternion2); extern inline int bgc_quaternion_are_close_fp32(const BgcQuaternionFP32* quaternion1, const BgcQuaternionFP32* quaternion2); diff --git a/basic-geometry/quaternion.h b/basic-geometry/quaternion.h index c88b66b..54be3fa 100644 --- a/basic-geometry/quaternion.h +++ b/basic-geometry/quaternion.h @@ -659,6 +659,8 @@ inline int bgc_quaternion_get_reverse_matrix_fp64(const BgcQuaternionFP64* quate return 1; } +// ============= Get Both Matrixes ============== // + inline int bgc_quaternion_get_both_matrixes_fp32(const BgcQuaternionFP32* quaternion, BgcMatrix3x3FP32* rotation, BgcMatrix3x3FP32* reverse) { if (bgc_quaternion_get_reverse_matrix_fp32(quaternion, reverse)) { diff --git a/basic-geometry/tangent-pair.c b/basic-geometry/tangent-pair.c deleted file mode 100644 index c38571a..0000000 --- a/basic-geometry/tangent-pair.c +++ /dev/null @@ -1,79 +0,0 @@ -#include "tangent-pair.h" - -const BgcTangentPairFP32 BGC_IDLE_TANGENT_PAIR_FP32 = { 1.0f, 0.0f }; - -const BgcTangentPairFP64 BGC_IDLE_TANGENT_PAIR_FP64 = { 1.0, 0.0 }; - -extern inline void bgc_tangent_pair_reset_fp32(BgcTangentPairFP32* tangent); -extern inline void bgc_tangent_pair_reset_fp64(BgcTangentPairFP64* tangent); - -extern inline void bgc_tangent_pair_set_values_fp32(const float x1, const float x2, BgcTangentPairFP32* tangent); -extern inline void bgc_tangent_pair_set_values_fp64(const double x1, const double x2, BgcTangentPairFP64* tangent); - -extern inline void bgc_tangent_pair_set_turn_fp32(const float angle, const BgcAngleUnitEnum unit, BgcTangentPairFP32* tangent); -extern inline void bgc_tangent_pair_set_turn_fp64(const double angle, const BgcAngleUnitEnum unit, BgcTangentPairFP64* tangent); - -extern inline float bgc_tangent_pair_get_angle_fp32(const BgcTangentPairFP32* tangent, const BgcAngleUnitEnum unit); -extern inline double bgc_tangent_pair_get_angle_fp64(const BgcTangentPairFP64* tangent, const BgcAngleUnitEnum unit); - -extern inline void bgc_tangent_pair_copy_fp32(const BgcTangentPairFP32* source, BgcTangentPairFP32* destination); -extern inline void bgc_tangent_pair_copy_fp64(const BgcTangentPairFP64* source, BgcTangentPairFP64* destination); - -extern inline void bgc_tangent_pair_swap_fp32(BgcTangentPairFP32* tangent1, BgcTangentPairFP32* tangent2); -extern inline void bgc_tangent_pair_swap_fp64(BgcTangentPairFP64* tangent1, BgcTangentPairFP64* tangent2); - -extern inline void bgc_tangent_pair_convert_fp64_to_fp32(const BgcTangentPairFP64* source, BgcTangentPairFP32* destination); -extern inline void bgc_tangent_pair_convert_fp32_to_fp64(const BgcTangentPairFP32* source, BgcTangentPairFP64* destination); - -extern inline void bgc_tangent_pair_invert_fp32(const BgcTangentPairFP32* tangent, BgcTangentPairFP32* inverted); -extern inline void bgc_tangent_pair_invert_fp64(const BgcTangentPairFP64* tangent, BgcTangentPairFP64* inverted); - -extern inline void bgc_tangent_pair_combine_fp32(const BgcTangentPairFP32* tangent1, const BgcTangentPairFP32* tangent2, BgcTangentPairFP32* result); -extern inline void bgc_tangent_pair_combine_fp64(const BgcTangentPairFP64* tangent1, const BgcTangentPairFP64* tangent2, BgcTangentPairFP64* result); - -extern inline void bgc_tangent_pair_get_rotation_matrix_fp32(const BgcTangentPairFP32* tangent, BgcMatrix2x2FP32* matrix); -extern inline void bgc_tangent_pair_get_rotation_matrix_fp64(const BgcTangentPairFP64* tangent, BgcMatrix2x2FP64* matrix); - -extern inline void bgc_tangent_pair_get_reverse_matrix_fp32(const BgcTangentPairFP32* tangent, BgcMatrix2x2FP32* matrix); -extern inline void bgc_tangent_pair_get_reverse_matrix_fp64(const BgcTangentPairFP64* tangent, BgcMatrix2x2FP64* matrix); - -extern inline void bgc_tangent_pair_turn_vector_fp32(const BgcTangentPairFP32* tangent, const BgcVector2FP32* vector, BgcVector2FP32* result); -extern inline void bgc_tangent_pair_turn_vector_fp64(const BgcTangentPairFP64* tangent, const BgcVector2FP64* vector, BgcVector2FP64* result); - -extern inline void bgc_tangent_pair_turn_vector_back_fp32(const BgcTangentPairFP32* tangent, const BgcVector2FP32* vector, BgcVector2FP32* result); -extern inline void bgc_tangent_pair_turn_vector_back_fp64(const BgcTangentPairFP64* tangent, const BgcVector2FP64* vector, BgcVector2FP64* result); - -extern inline int bgc_tangent_pair_are_close_fp32(const BgcTangentPairFP32* tangent1, const BgcTangentPairFP32* tangent2); -extern inline int bgc_tangent_pair_are_close_fp64(const BgcTangentPairFP64* tangent1, const BgcTangentPairFP64* tangent2); - -void _bgc_tangent_pair_normalize_fp32(const float square_modulus, _BgcTwinTangentPairFP32* twin) -{ - // (square_modulus != square_modulus) is true when square_modulus is NaN - - if (square_modulus <= BGC_SQUARE_EPSYLON_FP32 || square_modulus != square_modulus) { - twin->cos = 1.0f; - twin->sin = 0.0f; - return; - } - - const float multiplier = sqrtf(1.0f / square_modulus); - - twin->cos *= multiplier; - twin->sin *= multiplier; -} - -void _bgc_tangent_pair_normalize_fp64(const double square_modulus, _BgcTwinTangentPairFP64* twin) -{ - // (square_modulus != square_modulus) is true when square_modulus is NaN - - if (square_modulus <= BGC_SQUARE_EPSYLON_FP64 || square_modulus != square_modulus) { - twin->cos = 1.0; - twin->sin = 0.0; - return; - } - - const double multiplier = sqrt(1.0 / square_modulus); - - twin->cos *= multiplier; - twin->sin *= multiplier; -} diff --git a/basic-geometry/tangent-pair.h b/basic-geometry/tangent-pair.h deleted file mode 100644 index 40c5c15..0000000 --- a/basic-geometry/tangent-pair.h +++ /dev/null @@ -1,352 +0,0 @@ -#ifndef _bgc_tangent_pair_H_ -#define _bgc_tangent_pair_H_ - -#include - -#include "utilities.h" -#include "angle.h" -#include "vector2.h" -#include "matrix2x2.h" - -// =================== Types ==================== // - -typedef struct -{ - const float cos, sin; -} BgcTangentPairFP32; - -typedef struct -{ - const double cos, sin; -} BgcTangentPairFP64; - -// ================= Dark Twins ================= // - -typedef struct { - float cos, sin; -} _BgcTwinTangentPairFP32; - -typedef struct { - double cos, sin; -} _BgcTwinTangentPairFP64; - -// ================= Constants ================== // - -extern const BgcTangentPairFP32 BGC_IDLE_TANGENT_PAIR_FP32; -extern const BgcTangentPairFP64 BGC_IDLE_TANGENT_PAIR_FP64; - -// =================== Reset ==================== // - -inline void bgc_tangent_pair_reset_fp32(BgcTangentPairFP32* tangent) -{ - _BgcTwinTangentPairFP32* twin = (_BgcTwinTangentPairFP32*)tangent; - - twin->cos = 1.0f; - twin->sin = 0.0f; -} - -inline void bgc_tangent_pair_reset_fp64(BgcTangentPairFP64* tangent) -{ - _BgcTwinTangentPairFP64* twin = (_BgcTwinTangentPairFP64*)tangent; - - twin->cos = 1.0; - twin->sin = 0.0; -} - -// ==================== Set ===================== // - -void _bgc_tangent_pair_normalize_fp32(const float square_modulus, _BgcTwinTangentPairFP32* twin); - -void _bgc_tangent_pair_normalize_fp64(const double square_modulus, _BgcTwinTangentPairFP64* twin); - -inline void bgc_tangent_pair_set_values_fp32(const float x1, const float x2, BgcTangentPairFP32* tangent) -{ - const float square_modulus = x1 * x1 + x2 * x2; - - _BgcTwinTangentPairFP32* twin = (_BgcTwinTangentPairFP32*)tangent; - - twin->cos = x1; - twin->sin = x2; - - if (!bgc_is_sqare_unit_fp32(square_modulus)) { - _bgc_tangent_pair_normalize_fp32(square_modulus, twin); - } -} - -inline void bgc_tangent_pair_set_values_fp64(const double x1, const double x2, BgcTangentPairFP64* tangent) -{ - const double square_modulus = x1 * x1 + x2 * x2; - - _BgcTwinTangentPairFP64* twin = (_BgcTwinTangentPairFP64*)tangent; - - twin->cos = x1; - twin->sin = x2; - - if (!bgc_is_sqare_unit_fp64(square_modulus)) { - _bgc_tangent_pair_normalize_fp64(square_modulus, twin); - } -} - -// ================== Set Turn ================== // - -inline void bgc_tangent_pair_set_turn_fp32(const float angle, const BgcAngleUnitEnum unit, BgcTangentPairFP32* tangent) -{ - const float radians = bgc_angle_to_radians_fp32(angle, unit); - - _BgcTwinTangentPairFP32* twin = (_BgcTwinTangentPairFP32*)tangent; - - twin->cos = cosf(radians); - twin->sin = sinf(radians); -} - -inline void bgc_tangent_pair_set_turn_fp64(const double angle, const BgcAngleUnitEnum unit, BgcTangentPairFP64* tangent) -{ - const double radians = bgc_angle_to_radians_fp64(angle, unit); - - _BgcTwinTangentPairFP64* twin = (_BgcTwinTangentPairFP64*)tangent; - - twin->cos = cos(radians); - twin->sin = sin(radians); -} - -// =================== Angle =================== // - -inline float bgc_tangent_pair_get_angle_fp32(const BgcTangentPairFP32* tangent, const BgcAngleUnitEnum unit) -{ - if (tangent->cos >= 1.0f - BGC_EPSYLON_FP32) { - return 0.0f; - } - - if (tangent->cos <= -1.0f + BGC_EPSYLON_FP32) { - return bgc_angle_get_half_circle_fp32(unit); - } - - if (tangent->sin >= 1.0f - BGC_EPSYLON_FP32) { - return bgc_angle_get_quater_circle_fp32(unit); - } - - if (tangent->sin <= -1.0f + BGC_EPSYLON_FP32) { - return 0.75f * bgc_angle_get_full_circle_fp32(unit); - } - - return bgc_radians_to_units_fp32(atan2f(tangent->sin, tangent->cos), unit); -} - -inline double bgc_tangent_pair_get_angle_fp64(const BgcTangentPairFP64* tangent, const BgcAngleUnitEnum unit) -{ - if (tangent->cos >= 1.0 - BGC_EPSYLON_FP64) { - return 0.0; - } - - if (tangent->cos <= -1.0 + BGC_EPSYLON_FP64) { - return bgc_angle_get_half_circle_fp64(unit); - } - - if (tangent->sin >= 1.0 - BGC_EPSYLON_FP64) { - return bgc_angle_get_quater_circle_fp64(unit); - } - - if (tangent->sin <= -1.0 + BGC_EPSYLON_FP64) { - return 0.75 * bgc_angle_get_full_circle_fp64(unit); - } - - return bgc_radians_to_units_fp64(atan2(tangent->sin, tangent->cos), unit); -} - -// ==================== Copy ==================== // - -inline void bgc_tangent_pair_copy_fp32(const BgcTangentPairFP32* source, BgcTangentPairFP32* destination) -{ - _BgcTwinTangentPairFP32* twin = (_BgcTwinTangentPairFP32*)destination; - - twin->cos = source->cos; - twin->sin = source->sin; -} - -inline void bgc_tangent_pair_copy_fp64(const BgcTangentPairFP64* source, BgcTangentPairFP64* destination) -{ - _BgcTwinTangentPairFP64* twin = (_BgcTwinTangentPairFP64*)destination; - - twin->cos = source->cos; - twin->sin = source->sin; -} - -// ==================== Swap ==================== // - -inline void bgc_tangent_pair_swap_fp32(BgcTangentPairFP32* tangent1, BgcTangentPairFP32* tangent2) -{ - const float cos = tangent1->cos; - const float sin = tangent1->sin; - - _BgcTwinTangentPairFP32* twin1 = (_BgcTwinTangentPairFP32*)tangent1; - - twin1->cos = tangent2->cos; - twin1->sin = tangent2->sin; - - _BgcTwinTangentPairFP32* twin2 = (_BgcTwinTangentPairFP32*)tangent2; - - twin2->cos = cos; - twin2->sin = sin; -} - -inline void bgc_tangent_pair_swap_fp64(BgcTangentPairFP64* tangent1, BgcTangentPairFP64* tangent2) -{ - const double cos = tangent1->cos; - const double sin = tangent1->sin; - - _BgcTwinTangentPairFP64* twin1 = (_BgcTwinTangentPairFP64*)tangent1; - - twin1->cos = tangent2->cos; - twin1->sin = tangent2->sin; - - _BgcTwinTangentPairFP64* twin2 = (_BgcTwinTangentPairFP64*)tangent2; - - twin2->cos = cos; - twin2->sin = sin; -} - -// ================== Convert =================== // - -inline void bgc_tangent_pair_convert_fp64_to_fp32(const BgcTangentPairFP64* source, BgcTangentPairFP32* destination) -{ - bgc_tangent_pair_set_values_fp32((float)source->cos, (float)source->sin, destination); -} - -inline void bgc_tangent_pair_convert_fp32_to_fp64(const BgcTangentPairFP32* source, BgcTangentPairFP64* destination) -{ - bgc_tangent_pair_set_values_fp64((double)source->cos, (double)source->sin, destination); -} - -// =================== Invert =================== // - -inline void bgc_tangent_pair_invert_fp32(const BgcTangentPairFP32* tangent, BgcTangentPairFP32* inverted) -{ - _BgcTwinTangentPairFP32* twin = (_BgcTwinTangentPairFP32*)inverted; - - twin->cos = tangent->cos; - twin->sin = -tangent->sin; -} - -inline void bgc_tangent_pair_invert_fp64(const BgcTangentPairFP64* tangent, BgcTangentPairFP64* inverted) -{ - _BgcTwinTangentPairFP64* twin = (_BgcTwinTangentPairFP64*)inverted; - - twin->cos = tangent->cos; - twin->sin = -tangent->sin; -} - -// ================ Combination ================= // - -inline void bgc_tangent_pair_combine_fp32(const BgcTangentPairFP32* tangent1, const BgcTangentPairFP32* tangent2, BgcTangentPairFP32* result) -{ - bgc_tangent_pair_set_values_fp32( - tangent1->cos * tangent2->cos - tangent1->sin * tangent2->sin, - tangent1->cos * tangent2->sin + tangent1->sin * tangent2->cos, - result - ); -} - -inline void bgc_tangent_pair_combine_fp64(const BgcTangentPairFP64* tangent1, const BgcTangentPairFP64* tangent2, BgcTangentPairFP64* result) -{ - bgc_tangent_pair_set_values_fp64( - tangent1->cos * tangent2->cos - tangent1->sin * tangent2->sin, - tangent1->cos * tangent2->sin + tangent1->sin * tangent2->cos, - result - ); -} - -// ============== Rotation Matrix =============== // - -inline void bgc_tangent_pair_get_rotation_matrix_fp32(const BgcTangentPairFP32* tangent, BgcMatrix2x2FP32* matrix) -{ - matrix->r1c1 = tangent->cos; - matrix->r1c2 = -tangent->sin; - matrix->r2c1 = tangent->sin; - matrix->r2c2 = tangent->cos; -} - -inline void bgc_tangent_pair_get_rotation_matrix_fp64(const BgcTangentPairFP64* tangent, BgcMatrix2x2FP64* matrix) -{ - matrix->r1c1 = tangent->cos; - matrix->r1c2 = -tangent->sin; - matrix->r2c1 = tangent->sin; - matrix->r2c2 = tangent->cos; -} - -// ============== Reverse Matrix ================ // - -inline void bgc_tangent_pair_get_reverse_matrix_fp32(const BgcTangentPairFP32* tangent, BgcMatrix2x2FP32* matrix) -{ - matrix->r1c1 = tangent->cos; - matrix->r1c2 = tangent->sin; - matrix->r2c1 = -tangent->sin; - matrix->r2c2 = tangent->cos; -} - -inline void bgc_tangent_pair_get_reverse_matrix_fp64(const BgcTangentPairFP64* tangent, BgcMatrix2x2FP64* matrix) -{ - matrix->r1c1 = tangent->cos; - matrix->r1c2 = tangent->sin; - matrix->r2c1 = -tangent->sin; - matrix->r2c2 = tangent->cos; -} - -// ================ Turn Vector ================= // - -inline void bgc_tangent_pair_turn_vector_fp32(const BgcTangentPairFP32* tangent, const BgcVector2FP32* vector, BgcVector2FP32* result) -{ - const float x1 = tangent->cos * vector->x1 - tangent->sin * vector->x2; - const float x2 = tangent->sin * vector->x1 + tangent->cos * vector->x2; - - result->x1 = x1; - result->x2 = x2; -} - -inline void bgc_tangent_pair_turn_vector_fp64(const BgcTangentPairFP64* tangent, const BgcVector2FP64* vector, BgcVector2FP64* result) -{ - const double x1 = tangent->cos * vector->x1 - tangent->sin * vector->x2; - const double x2 = tangent->sin * vector->x1 + tangent->cos * vector->x2; - - result->x1 = x1; - result->x2 = x2; -} - -// ============ Turn Vector Backward ============ // - -inline void bgc_tangent_pair_turn_vector_back_fp32(const BgcTangentPairFP32* tangent, const BgcVector2FP32* vector, BgcVector2FP32* result) -{ - const float x1 = tangent->sin * vector->x2 + tangent->cos * vector->x1; - const float x2 = tangent->cos * vector->x2 - tangent->sin * vector->x1; - - result->x1 = x1; - result->x2 = x2; -} - -inline void bgc_tangent_pair_turn_vector_back_fp64(const BgcTangentPairFP64* tangent, const BgcVector2FP64* vector, BgcVector2FP64* result) -{ - const double x1 = tangent->sin * vector->x2 + tangent->cos * vector->x1; - const double x2 = tangent->cos * vector->x2 - tangent->sin * vector->x1; - - result->x1 = x1; - result->x2 = x2; -} - -// ================== Are Close ================= // - -inline int bgc_tangent_pair_are_close_fp32(const BgcTangentPairFP32* tangent1, const BgcTangentPairFP32* tangent2) -{ - const float d_cos = tangent1->cos - tangent2->cos; - const float d_sin = tangent1->sin - tangent2->sin; - - return d_cos * d_cos + d_sin * d_sin <= BGC_SQUARE_EPSYLON_FP32; -} - -inline int bgc_tangent_pair_are_close_fp64(const BgcTangentPairFP64* tangent1, const BgcTangentPairFP64* tangent2) -{ - const double d_cos = tangent1->cos - tangent2->cos; - const double d_sin = tangent1->sin - tangent2->sin; - - return d_cos * d_cos + d_sin * d_sin <= BGC_SQUARE_EPSYLON_FP64; -} - -#endif diff --git a/basic-geometry/vector2.c b/basic-geometry/vector2.c index af738d4..b0b7c64 100644 --- a/basic-geometry/vector2.c +++ b/basic-geometry/vector2.c @@ -33,12 +33,6 @@ extern inline void bgc_vector2_reverse_fp64(const BgcVector2FP64* vector, BgcVec extern inline int bgc_vector2_normalize_fp32(const BgcVector2FP32* vector, BgcVector2FP32* normalized); extern inline int bgc_vector2_normalize_fp64(const BgcVector2FP64* vector, BgcVector2FP64* normalized); -extern inline void bgc_vector2_complex_conjugate_fp32(const BgcVector2FP32* vector, BgcVector2FP32* conjugate); -extern inline void bgc_vector2_complex_conjugate_fp64(const BgcVector2FP64* vector, BgcVector2FP64* conjugate); - -extern inline int bgc_vector2_complex_invert_fp32(const BgcVector2FP32* vector, BgcVector2FP32* inverted); -extern inline int bgc_vector2_complex_invert_fp64(const BgcVector2FP64* vector, BgcVector2FP64* inverted); - extern inline void bgc_vector2_add_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2, BgcVector2FP32* sum); extern inline void bgc_vector2_add_fp64(const BgcVector2FP64* vector1, const BgcVector2FP64* vector2, BgcVector2FP64* sum); @@ -78,12 +72,6 @@ extern inline double bgc_vector2_get_scalar_product_fp64(const BgcVector2FP64* v extern inline float bgc_vector2_get_cross_product_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2); extern inline double bgc_vector2_get_cross_product_fp64(const BgcVector2FP64* vector1, const BgcVector2FP64* vector2); -extern inline void bgc_vector2_get_complex_product_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2, BgcVector2FP32* product); -extern inline void bgc_vector2_get_complex_product_fp64(const BgcVector2FP64* vector1, const BgcVector2FP64* vector2, BgcVector2FP64* product); - -extern inline int bgc_vector2_get_complex_ratio_fp32(const BgcVector2FP32* divident, const BgcVector2FP32* divisor, BgcVector2FP32* quotient); -extern inline int bgc_vector2_get_complex_ratio_fp64(const BgcVector2FP64* divident, const BgcVector2FP64* divisor, BgcVector2FP64* quotient); - extern inline float bgc_vector2_get_square_distance_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2); extern inline double bgc_vector2_get_square_distance_fp64(const BgcVector2FP64* vector1, const BgcVector2FP64* vector2); @@ -96,48 +84,6 @@ extern inline int bgc_vector2_are_close_enough_fp64(const BgcVector2FP64* vector extern inline int bgc_vector2_are_close_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2); extern inline int bgc_vector2_are_close_fp64(const BgcVector2FP64* vector1, const BgcVector2FP64* vector2); -// =============== Complex Power ================ // - -void bgc_vector2_get_complex_power_fp32(const BgcVector2FP32* base, const BgcVector2FP32* power, BgcVector2FP32* result) -{ - const float base_square_modulus = bgc_vector2_get_square_modulus_fp32(base); - - if (base_square_modulus <= BGC_SQUARE_EPSYLON_FP32) { - result->x1 = 0.0f; - result->x2 = 0.0f; - return; - } - - const float log_modulus = logf(base_square_modulus) * 0.5f; - const float angle = atan2f(base->x2, base->x1); - - const float result_modulus = expf(power->x1 * log_modulus - power->x2 * angle); - const float result_angle = power->x1 * angle + power->x2 * log_modulus; - - result->x1 = result_modulus * cosf(result_angle); - result->x2 = result_modulus * sinf(result_angle); -} - -void bgc_vector2_get_complex_power_fp64(const BgcVector2FP64* base, const BgcVector2FP64* power, BgcVector2FP64* result) -{ - const double base_square_modulus = bgc_vector2_get_square_modulus_fp64(base); - - if (base_square_modulus <= BGC_SQUARE_EPSYLON_FP64) { - result->x1 = 0.0; - result->x2 = 0.0; - return; - } - - const double log_modulus = log(base_square_modulus) * 0.5; - const double angle = atan2(base->x2, base->x1); - - const double result_modulus = exp(power->x1 * log_modulus - power->x2 * angle); - const double result_angle = power->x1 * angle + power->x2 * log_modulus; - - result->x1 = result_modulus * cos(result_angle); - result->x2 = result_modulus * sin(result_angle); -} - // =================== Angle ==================== // float bgc_vector2_get_angle_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2, const BgcAngleUnitEnum unit) diff --git a/basic-geometry/vector2.h b/basic-geometry/vector2.h index dc8ff3c..8852721 100644 --- a/basic-geometry/vector2.h +++ b/basic-geometry/vector2.h @@ -202,54 +202,6 @@ inline int bgc_vector2_normalize_fp64(const BgcVector2FP64* vector, BgcVector2FP return 1; } -// ============= Complex Conjugate ============== // - -inline void bgc_vector2_complex_conjugate_fp32(const BgcVector2FP32* vector, BgcVector2FP32* conjugate) -{ - conjugate->x1 = vector->x1; - conjugate->x2 = -vector->x2; -} - -inline void bgc_vector2_complex_conjugate_fp64(const BgcVector2FP64* vector, BgcVector2FP64* conjugate) -{ - conjugate->x1 = vector->x1; - conjugate->x2 = -vector->x2; -} - -// =============== Complex Invert =============== // - -inline int bgc_vector2_complex_invert_fp32(const BgcVector2FP32* vector, BgcVector2FP32* inverted) -{ - const float square_modulus = bgc_vector2_get_square_modulus_fp32(vector); - - if (square_modulus <= BGC_SQUARE_EPSYLON_FP32 || square_modulus != square_modulus) { - return 0; - } - - const float multiplicand = 1.0f / square_modulus; - - inverted->x1 = vector->x1 * multiplicand; - inverted->x2 = -vector->x2 * multiplicand; - - return 1; -} - -inline int bgc_vector2_complex_invert_fp64(const BgcVector2FP64* vector, BgcVector2FP64* inverted) -{ - const double square_modulus = bgc_vector2_get_square_modulus_fp64(vector); - - if (square_modulus <= BGC_SQUARE_EPSYLON_FP64 || square_modulus != square_modulus) { - return 0; - } - - const double multiplicand = 1.0 / square_modulus; - - inverted->x1 = vector->x1 * multiplicand; - inverted->x2 = -vector->x2 * multiplicand; - - return 1; -} - // ==================== Add ===================== // inline void bgc_vector2_add_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2, BgcVector2FP32* sum) @@ -450,72 +402,6 @@ inline double bgc_vector2_get_cross_product_fp64(const BgcVector2FP64* vector1, return vector1->x1 * vector2->x2 - vector1->x2 * vector2->x1; } -// ============ Get Complex Product ============= // - -inline void bgc_vector2_get_complex_product_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2, BgcVector2FP32* result) -{ - const float x1 = vector1->x1 * vector2->x1 - vector1->x2 * vector2->x2; - const float x2 = vector1->x1 * vector2->x2 + vector1->x2 * vector2->x1; - - result->x1 = x1; - result->x2 = x2; -} - -inline void bgc_vector2_get_complex_product_fp64(const BgcVector2FP64* vector1, const BgcVector2FP64* vector2, BgcVector2FP64* result) -{ - const double x1 = vector1->x1 * vector2->x1 - vector1->x2 * vector2->x2; - const double x2 = vector1->x1 * vector2->x2 + vector1->x2 * vector2->x1; - - result->x1 = x1; - result->x2 = x2; -} - -// ============= Get Complex Ratio ============== // - -inline int bgc_vector2_get_complex_ratio_fp32(const BgcVector2FP32* divident, const BgcVector2FP32* divisor, BgcVector2FP32* quotient) -{ - const float square_modulus = bgc_vector2_get_square_modulus_fp32(divisor); - - if (square_modulus <= BGC_SQUARE_EPSYLON_FP32) { - return 0; - } - - const float x1 = divident->x1 * divisor->x1 + divident->x2 * divisor->x2; - const float x2 = divident->x2 * divisor->x1 - divident->x1 * divisor->x2; - - const float multiplier = 1.0f / square_modulus; - - quotient->x1 = x1 * multiplier; - quotient->x2 = x2 * multiplier; - - return 1; -} - -inline int bgc_vector2_get_complex_ratio_fp64(const BgcVector2FP64* divident, const BgcVector2FP64* divisor, BgcVector2FP64* quotient) -{ - const double square_modulus = bgc_vector2_get_square_modulus_fp64(divisor); - - if (square_modulus <= BGC_SQUARE_EPSYLON_FP64) { - return 0; - } - - const double x1 = divident->x1 * divisor->x1 + divident->x2 * divisor->x2; - const double x2 = divident->x2 * divisor->x1 - divident->x1 * divisor->x2; - - const double multiplier = 1.0 / square_modulus; - - quotient->x1 = x1 * multiplier; - quotient->x2 = x2 * multiplier; - - return 1; -} - -// ============= Get Complex Power ============== // - -void bgc_vector2_get_complex_power_fp32(const BgcVector2FP32* base, const BgcVector2FP32* power, BgcVector2FP32* result); - -void bgc_vector2_get_complex_power_fp64(const BgcVector2FP64* base, const BgcVector2FP64* power, BgcVector2FP64* result); - // ================= Get Angle ================== // float bgc_vector2_get_angle_fp32(const BgcVector2FP32* vector1, const BgcVector2FP32* vector2, const BgcAngleUnitEnum unit); diff --git a/basic-geometry/versor.c b/basic-geometry/versor.c index 393b9ea..0fadc5c 100644 --- a/basic-geometry/versor.c +++ b/basic-geometry/versor.c @@ -158,17 +158,9 @@ void bgc_versor_get_rotation_fp32(const BgcVersorFP32* versor, BgcRotation3FP32* return; } - const float s0s0 = versor->s0 * versor->s0; - const float x1x1 = versor->x1 * versor->x1; - const float x2x2 = versor->x2 * versor->x2; - const float x3x3 = versor->x3 * versor->x3; + const float multiplier = sqrtf(1.0f / (versor->x1 * versor->x1 + versor->x2 * versor->x2 + versor->x3 * versor->x3)); - const float square_module = (s0s0 + x1x1) + (x2x2 + x3x3); - const float square_vector = x1x1 + (x2x2 + x3x3); - - result->radians = 2.0f * acosf(versor->s0 / sqrtf(square_module)); - - const float multiplier = sqrtf(1.0f / square_vector); + result->radians = 2.0f * acosf(versor->s0); result->axis.x1 = versor->x1 * multiplier; result->axis.x2 = versor->x2 * multiplier; @@ -182,19 +174,45 @@ void bgc_versor_get_rotation_fp64(const BgcVersorFP64* versor, BgcRotation3FP64* return; } - const double s0s0 = versor->s0 * versor->s0; - const double x1x1 = versor->x1 * versor->x1; - const double x2x2 = versor->x2 * versor->x2; - const double x3x3 = versor->x3 * versor->x3; + const double multiplier = sqrt(1.0 / (versor->x1 * versor->x1 + versor->x2 * versor->x2 + versor->x3 * versor->x3)); - const double square_module = (s0s0 + x1x1) + (x2x2 + x3x3); - const double square_vector = x1x1 + (x2x2 + x3x3); - - result->radians = 2.0 * acos(versor->s0 / sqrt(square_module)); - - const double multiplier = sqrt(1.0 / square_vector); + result->radians = 2.0 * acos(versor->s0); result->axis.x1 = versor->x1 * multiplier; result->axis.x2 = versor->x2 * multiplier; result->axis.x3 = versor->x3 * multiplier; } + +// =============== Get Exponation =============== // + +void bgc_versor_get_exponation_fp32(const BgcVersorFP32* base, const float exponent, BgcVersorFP32* power) +{ + const float square_vector = base->x1 * base->x1 + base->x2 * base->x2 + base->x3 * base->x3; + + if (square_vector <= BGC_SQUARE_EPSYLON_FP32) { + bgc_versor_reset_fp32(power); + return; + } + + const float angle = acosf(base->s0) * exponent; + + const float multiplier = sinf(angle) / sqrtf(square_vector); + + bgc_versor_set_values_fp32(cosf(angle), base->x1 * multiplier, base->x2 * multiplier, base->x3 * multiplier, power); +} + +void bgc_versor_get_exponation_fp64(const BgcVersorFP64* base, const double exponent, BgcVersorFP64* power) +{ + const double square_vector = base->x1 * base->x1 + base->x2 * base->x2 + base->x3 * base->x3; + + if (square_vector <= BGC_SQUARE_EPSYLON_FP64) { + bgc_versor_reset_fp64(power); + return; + } + + const double angle = acos(base->s0) * exponent; + + const double multiplier = sin(angle) / sqrt(square_vector); + + bgc_versor_set_values_fp64(cos(angle), base->x1 * multiplier, base->x2 * multiplier, base->x3 * multiplier, power); +} diff --git a/basic-geometry/versor.h b/basic-geometry/versor.h index e5ea79e..895d249 100644 --- a/basic-geometry/versor.h +++ b/basic-geometry/versor.h @@ -274,6 +274,12 @@ inline void bgc_versor_invert_fp64(const BgcVersorFP64* versor, BgcVersorFP64* i twin->x3 = -versor->x3; } +// =============== Get Exponation =============== // + +void bgc_versor_get_exponation_fp32(const BgcVersorFP32* base, const float exponent, BgcVersorFP32* power); + +void bgc_versor_get_exponation_fp64(const BgcVersorFP64* base, const double exponent, BgcVersorFP64* power); + // ================ Combination ================= // inline void bgc_versor_combine_fp32(const BgcVersorFP32* second, const BgcVersorFP32* first, BgcVersorFP32* result)