diff --git a/Geometry.workspace b/Geometry.workspace
index ed07c48..cd8d7cc 100644
--- a/Geometry.workspace
+++ b/Geometry.workspace
@@ -1,12 +1,12 @@
-
-
-
+
+
+
-
-
+
+
diff --git a/Geometry.workspace.layout b/Geometry.workspace.layout
index e46768a..a0fb322 100644
--- a/Geometry.workspace.layout
+++ b/Geometry.workspace.layout
@@ -1,5 +1,6 @@
-
+
+
diff --git a/GeometryC.sln b/GeometryC.sln
index 7e0cf58..ca7d87a 100644
--- a/GeometryC.sln
+++ b/GeometryC.sln
@@ -3,11 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32421.90
MinimumVisualStudioVersion = 10.0.40219.1
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "geometry", "src\geometry.vcxproj", "{40CA6FB4-135F-4D54-A8D9-7338BA56E6A7}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-geometry", "basic-geometry\basic-geometry.vcxproj", "{40CA6FB4-135F-4D54-A8D9-7338BA56E6A7}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "geometry-test", "test\geometry-test.vcxproj", "{48DAE315-715F-4044-ADF5-0308483B887C}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-geometry-test", "basic-geometry-test\basic-geometry-test.vcxproj", "{48DAE315-715F-4044-ADF5-0308483B887C}"
EndProject
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "geometry-dev", "dev\geometry-dev.vcxproj", "{46DE6C8F-3179-4652-95CF-28D44AC4774A}"
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "basic-geometry-dev", "basic-geometry-dev\basic-geometry-dev.vcxproj", "{46DE6C8F-3179-4652-95CF-28D44AC4774A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/basic-geometry-dev/basic-geometry-dev.cbp b/basic-geometry-dev/basic-geometry-dev.cbp
new file mode 100644
index 0000000..2dde9b3
--- /dev/null
+++ b/basic-geometry-dev/basic-geometry-dev.cbp
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/basic-geometry-dev/basic-geometry-dev.vcxproj b/basic-geometry-dev/basic-geometry-dev.vcxproj
new file mode 100644
index 0000000..125986d
--- /dev/null
+++ b/basic-geometry-dev/basic-geometry-dev.vcxproj
@@ -0,0 +1,165 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+ {40ca6fb4-135f-4d54-a8d9-7338ba56e6a7}
+
+
+
+ 16.0
+ Win32Proj
+ {46de6c8f-3179-4652-95cf-28d44ac4774a}
+ basic-geometry-dev
+ 10.0
+
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ CompileAsC
+ $(SolutionDir)src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ CompileAsC
+ $(SolutionDir)src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ CompileAsC
+ $(SolutionDir)src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ CompileAsC
+ MaxSpeed
+ $(SolutionDir)src;%(AdditionalIncludeDirectories)
+ Neither
+ Sync
+ NotSet
+ Precise
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/basic-geometry-dev/basic-geometry-dev.vcxproj.filters b/basic-geometry-dev/basic-geometry-dev.vcxproj.filters
new file mode 100644
index 0000000..48814f7
--- /dev/null
+++ b/basic-geometry-dev/basic-geometry-dev.vcxproj.filters
@@ -0,0 +1,22 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Исходные файлы
+
+
+
\ No newline at end of file
diff --git a/basic-geometry-dev/main.c b/basic-geometry-dev/main.c
new file mode 100644
index 0000000..e313c9d
--- /dev/null
+++ b/basic-geometry-dev/main.c
@@ -0,0 +1,194 @@
+#include
+#include
+#include
+#include
+
+#ifdef _WIN64
+#include
+#else
+#include
+#endif // _WINDOWS_
+
+BgFP32Versor * allocate_versors(const unsigned int amount)
+{
+ return calloc(amount, sizeof(BgFP32Versor));
+}
+
+BgFP32Versor * make_zero_versors(const unsigned int amount)
+{
+ BgFP32Versor * list = allocate_versors(amount);
+
+ if (list == 0) {
+ return 0;
+ }
+
+ for (unsigned int i = 0; i < amount; i++) {
+ bg_fp32_versor_reset(&list[i]);
+ }
+
+ return list;
+}
+
+BgFP32Versor * make_random_versors(const unsigned int amount)
+{
+ BgFP32Versor * list = allocate_versors(amount);
+
+ if (list == 0) {
+ return 0;
+ }
+
+ for (unsigned int i = 0; i < amount; i++) {
+ bg_fp32_versor_set_values(
+ (2.0f * rand()) / RAND_MAX - 1.0f,
+ (2.0f * rand()) / RAND_MAX - 1.0f,
+ (2.0f * rand()) / RAND_MAX - 1.0f,
+ (2.0f * rand()) / RAND_MAX - 1.0f,
+ &list[i]
+ );
+ }
+
+ return list;
+}
+
+void print_versor(const BgFP32Versor* versor)
+{
+ printf("(%f, %f, %f, %f)\n", versor->s0, versor->x1, versor->x2, versor->x3);
+}
+
+void print_vector(const BgFP32Vector3* vector)
+{
+ printf("(%f, %f, %f) / %f\n", vector->x1, vector->x2, vector->x3, bg_fp32_vector3_get_module(vector));
+}
+/*
+int main()
+{
+ const unsigned int amount = 1000000;
+
+#ifdef _WIN64
+ ULONGLONG now;
+ now = GetTickCount64();
+ srand((unsigned int)(now & 0xfffffff));
+#else
+ struct timespec now;
+ clock_gettime(CLOCK_REALTIME, &now);
+ srand((unsigned int)(now.tv_nsec & 0xfffffff));
+#endif // _WIN64
+
+ BgFP32Versor * versors = make_random_versors(amount);
+
+ if (versors == 0) {
+ printf("Cannot allocate memory for versors");
+ return 0;
+ }
+
+ BgFP32Vector3 initial, result;
+
+ bg_fp32_vector3_set_values(1, 2, 3, &initial);
+ bg_fp32_vector3_copy(&initial, &result);
+
+#ifdef _WIN64
+ ULONGLONG start, end;
+ start = GetTickCount64();
+#else
+ struct timespec start, end;
+ clock_gettime(CLOCK_REALTIME, &start);
+#endif // _WIN64
+ for (unsigned int i = 0; i < amount; i++) {
+ bg_fp32_versor_turn2(&versors[i], &result, &result);
+ }
+
+ for (unsigned int i = amount; i > 0; i--) {
+ bg_fp32_versor_turn_back2(&versors[i - 1], &result, &result);
+ }
+
+#ifdef _WIN64
+ end = GetTickCount64();
+
+ printf("Time: %lld\n", end - start);
+#else
+ clock_gettime(CLOCK_REALTIME, &end);
+
+ printf("Time: %lf\n", (end.tv_sec - start.tv_sec) * 1000.0 + (end.tv_nsec - start.tv_nsec) * 0.000001);
+#endif // _WIN64
+
+
+ print_vector(&initial);
+ print_vector(&result);
+
+ free(versors);
+ return 0;
+}
+*/
+
+
+int main()
+{
+ const unsigned int amount = 1000000;
+
+#ifdef _WIN64
+ ULONGLONG now;
+ now = GetTickCount64();
+ srand((unsigned int)(now & 0xfffffff));
+#else
+ struct timespec now;
+ clock_gettime(CLOCK_REALTIME, &now);
+ srand((unsigned int)(now.tv_nsec & 0xfffffff));
+#endif // _WIN64
+
+ BgFP32Versor * versors1 = make_random_versors(amount);
+
+ if (versors1 == 0) {
+ printf("Cannot allocate memory for versors1");
+ return 0;
+ }
+
+ BgFP32Versor * versors2 = make_random_versors(amount);
+
+ if (versors2 == 0) {
+ printf("Cannot allocate memory for versors2");
+ free(versors1);
+ return 0;
+ }
+
+ BgFP32Versor * results = make_zero_versors(amount);
+
+ if (results == 0) {
+ printf("Cannot allocate memory for results");
+ free(versors2);
+ free(versors1);
+ return 0;
+ }
+
+#ifdef _WIN64
+ ULONGLONG start, end;
+ start = GetTickCount64();
+#else
+ struct timespec start, end;
+ clock_gettime(CLOCK_REALTIME, &start);
+#endif // _WIN64
+ for (int j = 0; j < 1000; j++) {
+ for (unsigned int i = 0; i < amount; i++) {
+ bg_fp32_versor_combine(&versors1[i], &versors2[i], &results[i]);
+ }
+ }
+
+#ifdef _WIN64
+ end = GetTickCount64();
+
+ printf("Time: %lld\n", end - start);
+#else
+ clock_gettime(CLOCK_REALTIME, &end);
+
+ printf("Time: %lf\n", (end.tv_sec - start.tv_sec) * 1000.0 + (end.tv_nsec - start.tv_nsec) * 0.000001);
+#endif // _WIN64
+
+ print_versor(versors1 + 10);
+ print_versor(versors2 + 10);
+ print_versor(results + 10);
+
+ free(results);
+ free(versors2);
+ free(versors1);
+ return 0;
+}
+
diff --git a/basic-geometry-test/basic-geometry-test.cbp b/basic-geometry-test/basic-geometry-test.cbp
new file mode 100644
index 0000000..f17f2d6
--- /dev/null
+++ b/basic-geometry-test/basic-geometry-test.cbp
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/basic-geometry-test/basic-geometry-test.vcxproj b/basic-geometry-test/basic-geometry-test.vcxproj
new file mode 100644
index 0000000..1283a6d
--- /dev/null
+++ b/basic-geometry-test/basic-geometry-test.vcxproj
@@ -0,0 +1,162 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+ 16.0
+ Win32Proj
+ {48dae315-715f-4044-adf5-0308483b887c}
+ basic-geometry-test
+ 10.0
+
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+ Application
+ true
+ v143
+ Unicode
+
+
+ Application
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+ Level3
+ true
+ _DEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
+ true
+ $(SolutionDir)src;%(AdditionalIncludeDirectories)
+
+
+ Console
+ true
+ true
+ true
+
+
+
+
+ {40ca6fb4-135f-4d54-a8d9-7338ba56e6a7}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/basic-geometry-test/basic-geometry-test.vcxproj.filters b/basic-geometry-test/basic-geometry-test.vcxproj.filters
new file mode 100644
index 0000000..d7e4b49
--- /dev/null
+++ b/basic-geometry-test/basic-geometry-test.vcxproj.filters
@@ -0,0 +1,36 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Исходные файлы
+
+
+ Исходные файлы
+
+
+ Исходные файлы
+
+
+
+
+ Исходные файлы
+
+
+ Исходные файлы
+
+
+
\ No newline at end of file
diff --git a/basic-geometry-test/fp32_vector2_test.c b/basic-geometry-test/fp32_vector2_test.c
new file mode 100644
index 0000000..c5bbc81
--- /dev/null
+++ b/basic-geometry-test/fp32_vector2_test.c
@@ -0,0 +1,150 @@
+#include "fp32_vector2_test.h"
+
+const int TEST_BG_FP32_VECTOR2_AMOUNT_1 = 5;
+
+const BgFP32Vector2 TEST_BG_FP32_VECTOR2_COMMON_1[] = {
+ { 3.0f, 4.0f },
+ { -3.0f, -4.0f },
+ { 10000.0f, -20000.0f },
+ { 0.1f, -10.0f },
+ { -123.5f, 3.7283f }
+};
+
+const BgFP32Vector2 TEST_BG_FP32_VECTOR2_COMMON_2[] = {
+ { -3.0f, -4.0f },
+ { -3.0f, -4.0f },
+ { 0.002f, -0.05f },
+ { -0.2f, 12.0f },
+ { 1.5f, -23.35f }
+};
+
+// =============== Square module ================ //
+
+const float BG_FP32_VECTOR2_SQUARE_MODULE_1[] = { 25.0f, 25.0f, 500000000.0f, 100.01f, 15266.150221f };
+
+int test_bg_fp32_vector2_square_module()
+{
+ print_test_name("BgFP32Vector2 square module");
+
+ float square_module;
+
+ for (int i = 0; i < TEST_BG_FP32_VECTOR2_AMOUNT_1; i++) {
+ square_module = bg_fp32_vector2_get_square_module(&TEST_BG_FP32_VECTOR2_COMMON_1[i]);
+
+ if (!test_bg_fp32_are_equal(square_module, BG_FP32_VECTOR2_SQUARE_MODULE_1[i], TEST_BG_FP32_TWO_EPSYLON)) {
+ print_test_failed();
+ return TEST_RESULT_FAILED;
+ }
+ }
+
+ print_test_success();
+ return TEST_RESULT_SUCCES;
+}
+
+// =================== Module =================== //
+
+const float BG_FP32_VECTOR2_MODULE_1[] = { 5.0f, 5.0f, 22360.68f, 10.0005f, 123.55626338f };
+
+int test_bg_fp32_vector2_module()
+{
+ print_test_name("BgFP32Vector2 module");
+
+ float square_module;
+
+ for (int i = 0; i < TEST_BG_FP32_VECTOR2_AMOUNT_1; i++) {
+ square_module = bg_fp32_vector2_get_module(&TEST_BG_FP32_VECTOR2_COMMON_1[i]);
+
+ if (!test_bg_fp32_are_equal(square_module, BG_FP32_VECTOR2_MODULE_1[i], TEST_BG_FP32_EPSYLON)) {
+ print_test_failed();
+ return TEST_RESULT_FAILED;
+ }
+ }
+
+ print_test_success();
+ return TEST_RESULT_SUCCES;
+}
+
+// ===================== Add ==================== //
+
+const BgFP32Vector2 TEST_BG_FP32_VECTOR2_COMMON_1_2_SUM[] = {
+ { 0.0f, 0.0f },
+ { -6.0f, -8.0f },
+ { 10000.002f, -20000.05f },
+ { -0.1f, 2.0f },
+ { -122.0f, -19.6217f }
+};
+
+int test_bg_fp32_vector2_add()
+{
+ print_test_name("BgFP32Vector2 add");
+
+ BgFP32Vector2 vector;
+
+ for (int i = 0; i < TEST_BG_FP32_VECTOR2_AMOUNT_1; i++) {
+ bg_fp32_vector2_add(&TEST_BG_FP32_VECTOR2_COMMON_1[i], &TEST_BG_FP32_VECTOR2_COMMON_2[i], &vector);
+
+ if (!test_bg_fp32_are_equal(vector.x1, TEST_BG_FP32_VECTOR2_COMMON_1_2_SUM[i].x1, TEST_BG_FP32_EPSYLON) ||
+ !test_bg_fp32_are_equal(vector.x2, TEST_BG_FP32_VECTOR2_COMMON_1_2_SUM[i].x2, TEST_BG_FP32_EPSYLON)) {
+ print_test_failed();
+ return TEST_RESULT_FAILED;
+ }
+ }
+
+ print_test_success();
+ return TEST_RESULT_SUCCES;
+}
+
+// ================== Subtract ================== //
+
+const BgFP32Vector2 TEST_BG_FP32_VECTOR2_COMMON_1_2_DIFF[] = {
+ { 6.0f, 8.0f },
+ { 0.0f, 0.0f },
+ { 9999.998f, -19999.95f },
+ { 0.3f, -22.0f },
+ { -125.0f, 27.0783f }
+};
+
+int test_bg_fp32_vector2_subtract()
+{
+ print_test_name("BgFP32Vector2 subtract");
+
+ BgFP32Vector2 vector;
+
+ for (int i = 0; i < TEST_BG_FP32_VECTOR2_AMOUNT_1; i++) {
+ bg_fp32_vector2_subtract(&TEST_BG_FP32_VECTOR2_COMMON_1[i], &TEST_BG_FP32_VECTOR2_COMMON_2[i], &vector);
+
+ if (!test_bg_fp32_are_equal(vector.x1, TEST_BG_FP32_VECTOR2_COMMON_1_2_DIFF[i].x1, TEST_BG_FP32_EPSYLON) ||
+ !test_bg_fp32_are_equal(vector.x2, TEST_BG_FP32_VECTOR2_COMMON_1_2_DIFF[i].x2, TEST_BG_FP32_EPSYLON)) {
+ print_test_failed();
+ return TEST_RESULT_FAILED;
+ }
+ }
+
+ print_test_success();
+ return TEST_RESULT_SUCCES;
+}
+
+// ==================== 1234 ==================== //
+
+int test_bg_fp32_vector2()
+{
+ print_test_section("BgFP32Vector2");
+
+ if (test_bg_fp32_vector2_square_module() != TEST_RESULT_SUCCES) {
+ return TEST_RESULT_FAILED;
+ }
+
+ if (test_bg_fp32_vector2_module() != TEST_RESULT_SUCCES) {
+ return TEST_RESULT_FAILED;
+ }
+
+ if (test_bg_fp32_vector2_add() != TEST_RESULT_SUCCES) {
+ return TEST_RESULT_FAILED;
+ }
+
+ if (test_bg_fp32_vector2_subtract() != TEST_RESULT_SUCCES) {
+ return TEST_RESULT_FAILED;
+ }
+
+ return TEST_RESULT_SUCCES;
+}
diff --git a/basic-geometry-test/fp32_vector2_test.h b/basic-geometry-test/fp32_vector2_test.h
new file mode 100644
index 0000000..ef16f2b
--- /dev/null
+++ b/basic-geometry-test/fp32_vector2_test.h
@@ -0,0 +1,16 @@
+#ifndef __GEOMETRY_VECTOR2_FLOAT_TEST_H__
+#define __GEOMETRY_VECTOR2_FLOAT_TEST_H__
+
+#include "geometry_test.h"
+
+int test_bg_fp32_vector2();
+
+int test_bg_fp32_vector2_square_module();
+
+int test_bg_fp32_vector2_module();
+
+int test_bg_fp32_vector2_add();
+
+int test_bg_fp32_vector2_subtract();
+
+#endif
diff --git a/basic-geometry-test/geometry_test.c b/basic-geometry-test/geometry_test.c
new file mode 100644
index 0000000..b6f5de5
--- /dev/null
+++ b/basic-geometry-test/geometry_test.c
@@ -0,0 +1,23 @@
+#include "geometry_test.h"
+
+#include
+
+void print_test_section(const char * name)
+{
+ printf("================ %s ================\n", name);
+}
+
+void print_test_name(const char * name)
+{
+ printf(" Testing of %s: ", name);
+}
+
+void print_test_success()
+{
+ printf("[ \x1b[32mSuccess\x1b[0m ]\n");
+}
+
+void print_test_failed()
+{
+ printf("[ \x1b[31mFailed\x1b[0m ]\n");
+}
diff --git a/basic-geometry-test/geometry_test.h b/basic-geometry-test/geometry_test.h
new file mode 100644
index 0000000..5f9c868
--- /dev/null
+++ b/basic-geometry-test/geometry_test.h
@@ -0,0 +1,53 @@
+#ifndef __GEOMETRY_TEST_H__
+#define __GEOMETRY_TEST_H__
+
+#include
+
+#define TEST_RESULT_SUCCES 0
+#define TEST_RESULT_FAILED 100
+
+#define TEST_BG_FP32_EPSYLON 1E-6f
+#define TEST_BG_FP32_TWO_EPSYLON 2E-6f
+#define TEST_BG_FP32_SQUARE_EPSYLON 1E-12f
+
+#define TEST_BG_FP64_EPSYLON 1E-13f
+#define TEST_BG_FP64_TWO_EPSYLON 2E-13f
+#define TEST_BG_FP64_SQUARE_EPSYLON 1E-26f
+
+void print_test_section(const char * name);
+
+void print_test_name(const char * name);
+
+void print_test_success();
+
+void print_test_failed();
+
+inline int test_bg_fp32_are_equal(const float value1, const float value2, const float epsylon)
+{
+ if (-1.0f <= value1 && value1 <= 1.0f) {
+ const float difference = value1 - value2;
+ return -epsylon <= difference && difference <= epsylon;
+ }
+
+ if (value1 > 0.0f) {
+ return value1 <= value2 * (1.0f + epsylon) && value2 <= value1 * (1.0f + epsylon);
+ }
+
+ return value1 * (1.0f + epsylon) <= value2 && value2 * (1.0f + epsylon) <= value1;
+}
+
+inline int test_bg_fp64_are_equal(const double value1, const double value2, const double epsylon)
+{
+ if (-1.0 <= value1 && value1 <= 1.0) {
+ const double difference = value1 - value2;
+ return -epsylon <= difference && difference <= epsylon;
+ }
+
+ if (value1 > 0.0) {
+ return value1 <= value2 * (1.0 + epsylon) && value2 <= value1 * (1.0 + epsylon);
+ }
+
+ return value1 * (1.0 + epsylon) <= value2 && value2 * (1.0 + epsylon) <= value1;
+}
+
+#endif
diff --git a/basic-geometry-test/main.c b/basic-geometry-test/main.c
new file mode 100644
index 0000000..f47ea7d
--- /dev/null
+++ b/basic-geometry-test/main.c
@@ -0,0 +1,17 @@
+#include
+#include
+
+#include "geometry_test.h"
+#include "fp32_vector2_test.h"
+
+#define PROGRAM_RESULT_SUCCESS 0
+#define PROGRAM_RESULT_FAILED 1
+
+int main()
+{
+ if (test_bg_fp32_vector2() == TEST_RESULT_FAILED) {
+ return PROGRAM_RESULT_FAILED;
+ }
+
+ return PROGRAM_RESULT_SUCCESS;
+}
diff --git a/basic-geometry/angle.c b/basic-geometry/angle.c
new file mode 100644
index 0000000..b7b0313
--- /dev/null
+++ b/basic-geometry/angle.c
@@ -0,0 +1,3 @@
+#include "basis.h"
+#include "angle.h"
+
diff --git a/basic-geometry/angle.h b/basic-geometry/angle.h
new file mode 100644
index 0000000..91f2753
--- /dev/null
+++ b/basic-geometry/angle.h
@@ -0,0 +1,557 @@
+#ifndef _GEOMETRY_ANGLE_H_
+#define _GEOMETRY_ANGLE_H_
+
+#include
+#include "basis.h"
+
+#define BG_FP32_PI 3.1415926536f
+#define BG_FP32_TWO_PI 6.2831853072f
+#define BG_FP32_HALF_OF_PI 1.5707963268f
+#define BG_FP32_THIRD_OF_PI 1.0471975512f
+#define BG_FP32_FOURTH_OF_PI 0.7853981634f
+#define BG_FP32_SIXTH_OF_PI 0.5235987756f
+
+#define BG_FP32_DEGREES_IN_RADIAN 57.295779513f
+#define BG_FP32_TURNS_IN_RADIAN 0.1591549431f
+#define BG_FP32_RADIANS_IN_DEGREE 1.745329252E-2f
+#define BG_FP32_TURNS_IN_DEGREE 2.7777777778E-3f
+
+#define BG_FP64_PI 3.14159265358979324
+#define BG_FP64_TWO_PI 6.28318530717958648
+#define BG_FP64_HALF_OF_PI 1.57079632679489662
+#define BG_FP64_THIRD_OF_PI 1.04719755119659775
+#define BG_FP64_FOURTH_OF_PI 0.78539816339744831
+#define BG_FP64_SIXTH_OF_PI 0.523598775598298873
+
+#define BG_FP64_DEGREES_IN_RADIAN 57.2957795130823209
+#define BG_FP64_TURNS_IN_RADIAN 0.159154943091895336
+#define BG_FP64_RADIANS_IN_DEGREE 1.74532925199432958E-2
+#define BG_FP64_TURNS_IN_DEGREE 2.77777777777777778E-3
+
+typedef enum {
+ BG_ANGLE_UNIT_RADIANS = 1,
+ BG_ANGLE_UNIT_DEGREES = 2,
+ BG_ANGLE_UNIT_TURNS = 3
+} angle_unit_t;
+
+typedef enum {
+ /**
+ * The measure of an angle with a range of:
+ * [0, 360) degrees, [0, 2xPI) radians, [0, 1) turns, [0, 400) gradians
+ */
+ BG_ANGLE_RANGE_UNSIGNED = 1,
+
+ /**
+ * The measure of an angle with a range of:
+ * (-180, 180] degrees, (-PI, PI] radians, (-0.5, 0.5] turns, (-200, 200] gradians
+ */
+ BG_ANGLE_RANGE_SIGNED = 2
+} angle_range_t;
+
+// !================= Radians ==================! //
+
+// ========= Convert radians to degrees ========= //
+
+static inline float bg_fp32_radians_to_degrees(const float radians)
+{
+ return radians * BG_FP32_DEGREES_IN_RADIAN;
+}
+
+static inline double bg_fp64_radians_to_degrees(const double radians)
+{
+ return radians * BG_FP64_DEGREES_IN_RADIAN;
+}
+
+// ========== Convert radians to turns ========== //
+
+static inline float bg_fp32_radians_to_turns(const float radians)
+{
+ return radians * BG_FP32_TURNS_IN_RADIAN;
+}
+
+static inline double bg_fp64_radians_to_turns(const double radians)
+{
+ return radians * BG_FP64_TURNS_IN_RADIAN;
+}
+
+// ========= Convert radians to any unit ======== //
+
+static inline float bg_fp32_radians_to_units(const float radians, const angle_unit_t to_unit)
+{
+ if (to_unit == BG_ANGLE_UNIT_DEGREES) {
+ return radians * BG_FP32_DEGREES_IN_RADIAN;
+ }
+
+ if (to_unit == BG_ANGLE_UNIT_TURNS) {
+ return radians * BG_FP32_TURNS_IN_RADIAN;
+ }
+
+ return radians;
+}
+
+static inline double bg_fp64_radians_to_units(const double radians, const angle_unit_t to_unit)
+{
+ if (to_unit == BG_ANGLE_UNIT_DEGREES) {
+ return radians * BG_FP64_DEGREES_IN_RADIAN;
+ }
+
+ if (to_unit == BG_ANGLE_UNIT_TURNS) {
+ return radians * BG_FP64_TURNS_IN_RADIAN;
+ }
+
+ return radians;
+}
+
+// ============ Normalize radians ============= //
+
+static inline float bg_fp32_radians_normalize(const float radians, const angle_range_t range)
+{
+ if (range == BG_ANGLE_RANGE_UNSIGNED) {
+ if (0.0f <= radians && radians < BG_FP32_TWO_PI) {
+ return radians;
+ }
+ }
+ else {
+ if (-BG_FP32_PI < radians && radians <= BG_FP32_PI) {
+ return radians;
+ }
+ }
+
+ float turns = radians * BG_FP32_TURNS_IN_RADIAN;
+
+ turns -= floorf(turns);
+
+ if (range == BG_ANGLE_RANGE_SIGNED && turns > 0.5f) {
+ turns -= 1.0f;
+ }
+
+ return turns * BG_FP32_TWO_PI;
+}
+
+static inline double bg_fp64_radians_normalize(const double radians, const angle_range_t range)
+{
+ if (range == BG_ANGLE_RANGE_UNSIGNED) {
+ if (0.0 <= radians && radians < BG_FP64_TWO_PI) {
+ return radians;
+ }
+ }
+ else {
+ if (-BG_FP64_PI < radians && radians <= BG_FP64_PI) {
+ return radians;
+ }
+ }
+
+ double turns = radians * BG_FP64_TURNS_IN_RADIAN;
+
+ turns -= floor(turns);
+
+ if (range == BG_ANGLE_RANGE_SIGNED && turns > 0.5) {
+ turns -= 1.0;
+ }
+
+ return turns * BG_FP64_TWO_PI;
+}
+
+// !================= Degrees ==================! //
+
+// ========= Convert degrees to radians ========= //
+
+static inline float bg_fp32_degrees_to_radians(const float degrees)
+{
+ return degrees * BG_FP32_RADIANS_IN_DEGREE;
+}
+
+static inline double bg_fp64_degrees_to_radians(const double degrees)
+{
+ return degrees * BG_FP64_RADIANS_IN_DEGREE;
+}
+
+// ========== Convert degrees to turns ========== //
+
+static inline float bg_fp32_degrees_to_turns(const float radians)
+{
+ return radians * BG_FP32_TURNS_IN_DEGREE;
+}
+
+static inline double bg_fp64_degrees_to_turns(const double radians)
+{
+ return radians * BG_FP64_TURNS_IN_DEGREE;
+}
+
+// ========= Convert degreess to any unit ======== //
+
+static inline float bg_fp32_degrees_to_units(const float degrees, const angle_unit_t to_unit)
+{
+ if (to_unit == BG_ANGLE_UNIT_RADIANS) {
+ return degrees * BG_FP32_RADIANS_IN_DEGREE;
+ }
+
+ if (to_unit == BG_ANGLE_UNIT_TURNS) {
+ return degrees * BG_FP32_TURNS_IN_DEGREE;
+ }
+
+ return degrees;
+}
+
+static inline double bg_fp64_degrees_to_units(const double degrees, const angle_unit_t to_unit)
+{
+ if (to_unit == BG_ANGLE_UNIT_RADIANS) {
+ return degrees * BG_FP64_RADIANS_IN_DEGREE;
+ }
+
+ if (to_unit == BG_ANGLE_UNIT_TURNS) {
+ return degrees * BG_FP64_TURNS_IN_DEGREE;
+ }
+
+ return degrees;
+}
+
+// ============ Normalize degrees ============= //
+
+static inline float bg_fp32_degrees_normalize(const float degrees, const angle_range_t range)
+{
+ if (range == BG_ANGLE_RANGE_UNSIGNED) {
+ if (0.0f <= degrees && degrees < 360.0f) {
+ return degrees;
+ }
+ }
+ else {
+ if (-180.0f < degrees && degrees <= 180.0f) {
+ return degrees;
+ }
+ }
+
+ float turns = degrees * BG_FP32_TURNS_IN_DEGREE;
+
+ turns -= floorf(turns);
+
+ if (range == BG_ANGLE_RANGE_SIGNED && turns > 0.5f) {
+ turns -= 1.0f;
+ }
+
+ return turns * 360.0f;
+}
+
+static inline double bg_fp64_degrees_normalize(const double degrees, const angle_range_t range)
+{
+ if (range == BG_ANGLE_RANGE_UNSIGNED) {
+ if (0.0 <= degrees && degrees < 360.0) {
+ return degrees;
+ }
+ }
+ else {
+ if (-180.0 < degrees && degrees <= 180.0) {
+ return degrees;
+ }
+ }
+
+ double turns = degrees * BG_FP64_TURNS_IN_DEGREE;
+
+ turns -= floor(turns);
+
+ if (range == BG_ANGLE_RANGE_SIGNED && turns > 0.5) {
+ turns -= 1.0;
+ }
+
+ return turns * 360.0;
+}
+
+// !================== Turns ===================! //
+
+// ========== Convert turns to radians ========== //
+
+static inline float bg_fp32_turns_to_radians(const float turns)
+{
+ return turns * BG_FP32_TWO_PI;
+}
+
+static inline double bg_fp64_turns_to_radians(const double turns)
+{
+ return turns * BG_FP64_TWO_PI;
+}
+
+// ========== Convert turns to degrees ========== //
+
+static inline float bg_fp32_turns_to_degrees(const float turns)
+{
+ return turns * 360.0f;
+}
+
+static inline double bg_fp64_turns_to_degrees(const double turns)
+{
+ return turns * 360.0;
+}
+
+// ========= Convert turns to any unit ======== //
+
+static inline float bg_fp32_turns_to_units(const float turns, const angle_unit_t to_unit)
+{
+ if (to_unit == BG_ANGLE_UNIT_RADIANS) {
+ return turns * BG_FP32_TWO_PI;
+ }
+
+ if (to_unit == BG_ANGLE_UNIT_DEGREES) {
+ return turns * 360.0f;
+ }
+
+ return turns;
+}
+
+static inline double bg_fp64_turns_to_units(const double turns, const angle_unit_t to_unit)
+{
+ if (to_unit == BG_ANGLE_UNIT_RADIANS) {
+ return turns * BG_FP64_TWO_PI;
+ }
+
+ if (to_unit == BG_ANGLE_UNIT_DEGREES) {
+ return turns * 360.0;
+ }
+
+ return turns;
+}
+
+// ============= Normalize turns ============== //
+
+static inline float bg_fp32_turns_normalize(const float turns, const angle_range_t range)
+{
+ if (range == BG_ANGLE_RANGE_UNSIGNED) {
+ if (0.0f <= turns && turns < 1.0f) {
+ return turns;
+ }
+ }
+ else {
+ if (-0.5f < turns && turns <= 0.5f) {
+ return turns;
+ }
+ }
+
+ float rest = turns - floorf(turns);
+
+ if (range == BG_ANGLE_RANGE_SIGNED && rest > 0.5f) {
+ return rest - 1.0f;
+ }
+
+ return rest;
+}
+
+static inline double bg_fp64_turns_normalize(const double turns, const angle_range_t range)
+{
+ if (range == BG_ANGLE_RANGE_UNSIGNED) {
+ if (0.0 <= turns && turns < 1.0) {
+ return turns;
+ }
+ }
+ else {
+ if (-0.5 < turns && turns <= 0.5) {
+ return turns;
+ }
+ }
+
+ double rest = turns - floor(turns);
+
+ if (range == BG_ANGLE_RANGE_SIGNED && rest > 0.5) {
+ return rest - 1.0;
+ }
+
+ return rest;
+}
+
+// !================== Angle ===================! //
+
+// ========= Convert any unit to radians ======== //
+
+static inline float bg_fp32_angle_to_radians(const float angle, const angle_unit_t unit)
+{
+ if (unit == BG_ANGLE_UNIT_DEGREES) {
+ return angle * BG_FP32_RADIANS_IN_DEGREE;
+ }
+
+ if (unit == BG_ANGLE_UNIT_TURNS) {
+ return angle * BG_FP32_TWO_PI;
+ }
+
+ return angle;
+}
+
+static inline double bg_fp64_angle_to_radians(const double angle, const angle_unit_t unit)
+{
+ if (unit == BG_ANGLE_UNIT_DEGREES) {
+ return angle * BG_FP64_RADIANS_IN_DEGREE;
+ }
+
+ if (unit == BG_ANGLE_UNIT_TURNS) {
+ return angle * BG_FP64_TWO_PI;
+ }
+
+ return angle;
+}
+
+// ========= Convert any unit to degreess ======== //
+
+static inline float bg_fp32_angle_to_degrees(const float angle, const angle_unit_t unit)
+{
+ if (unit == BG_ANGLE_UNIT_RADIANS) {
+ return angle * BG_FP32_DEGREES_IN_RADIAN;
+ }
+
+ if (unit == BG_ANGLE_UNIT_TURNS) {
+ return angle * 360.0f;
+ }
+
+ return angle;
+}
+
+static inline double bg_fp64_angle_to_degrees(const double angle, const angle_unit_t unit)
+{
+ if (unit == BG_ANGLE_UNIT_RADIANS) {
+ return angle * BG_FP64_DEGREES_IN_RADIAN;
+ }
+
+ if (unit == BG_ANGLE_UNIT_TURNS) {
+ return angle * 360.0;
+ }
+
+ return angle;
+}
+
+// ========= Convert any unit to turns ======== //
+
+static inline float bg_fp32_angle_to_turns(const float angle, const angle_unit_t unit)
+{
+ if (unit == BG_ANGLE_UNIT_RADIANS) {
+ return angle * BG_FP32_TURNS_IN_RADIAN;
+ }
+
+ if (unit == BG_ANGLE_UNIT_DEGREES) {
+ return angle * BG_FP32_TURNS_IN_DEGREE;
+ }
+
+ return angle;
+}
+
+static inline double bg_fp64_angle_to_turns(const double angle, const angle_unit_t unit)
+{
+ if (unit == BG_ANGLE_UNIT_RADIANS) {
+ return angle * BG_FP64_TURNS_IN_RADIAN;
+ }
+
+ if (unit == BG_ANGLE_UNIT_DEGREES) {
+ return angle * BG_FP64_TURNS_IN_DEGREE;
+ }
+
+ return angle;
+}
+
+// ============= Get Full Circle ============== //
+
+static inline float bg_fp32_angle_get_full_circle(const angle_unit_t unit)
+{
+ if (unit == BG_ANGLE_UNIT_DEGREES) {
+ return 360.0f;
+ }
+
+ if (unit == BG_ANGLE_UNIT_TURNS) {
+ return 1.0f;
+ }
+
+ return BG_FP32_TWO_PI;
+}
+
+static inline double bg_fp64_angle_get_full_circle(const angle_unit_t unit)
+{
+ if (unit == BG_ANGLE_UNIT_DEGREES) {
+ return 360.0;
+ }
+
+ if (unit == BG_ANGLE_UNIT_TURNS) {
+ return 1.0;
+ }
+
+ return BG_FP64_TWO_PI;
+}
+
+// ============= Get Half Circle ============== //
+
+static inline float bg_fp32_angle_get_half_circle(const angle_unit_t unit)
+{
+ if (unit == BG_ANGLE_UNIT_DEGREES) {
+ return 180.0f;
+ }
+
+ if (unit == BG_ANGLE_UNIT_TURNS) {
+ return 0.5f;
+ }
+
+ return BG_FP32_PI;
+}
+
+static inline double bg_fp64_angle_get_half_circle(const angle_unit_t unit)
+{
+ if (unit == BG_ANGLE_UNIT_DEGREES) {
+ return 180.0;
+ }
+
+ if (unit == BG_ANGLE_UNIT_TURNS) {
+ return 0.5;
+ }
+
+ return BG_FP64_PI;
+}
+
+// ============= Get Half Circle ============== //
+
+static inline float bg_fp32_angle_get_quater_circle(const angle_unit_t unit)
+{
+ if (unit == BG_ANGLE_UNIT_DEGREES) {
+ return 90.0f;
+ }
+
+ if (unit == BG_ANGLE_UNIT_TURNS) {
+ return 0.25f;
+ }
+
+ return BG_FP32_HALF_OF_PI;
+}
+
+static inline double bg_fp64_angle_get_quater_circle(const angle_unit_t unit)
+{
+ if (unit == BG_ANGLE_UNIT_DEGREES) {
+ return 90.0;
+ }
+
+ if (unit == BG_ANGLE_UNIT_TURNS) {
+ return 0.25;
+ }
+
+ return BG_FP64_HALF_OF_PI;
+}
+
+// ================ Normalize ================= //
+
+static inline float bg_fp32_angle_normalize(const float angle, const angle_unit_t unit, const angle_range_t range)
+{
+ if (unit == BG_ANGLE_UNIT_DEGREES) {
+ return bg_fp32_degrees_normalize(angle, range);
+ }
+
+ if (unit == BG_ANGLE_UNIT_TURNS) {
+ return bg_fp32_turns_normalize(angle, range);
+ }
+
+ return bg_fp32_radians_normalize(angle, range);
+}
+
+static inline double bg_fp64_angle_normalize(const double angle, const angle_unit_t unit, const angle_range_t range)
+{
+ if (unit == BG_ANGLE_UNIT_DEGREES) {
+ return bg_fp64_degrees_normalize(angle, range);
+ }
+
+ if (unit == BG_ANGLE_UNIT_TURNS) {
+ return bg_fp64_turns_normalize(angle, range);
+ }
+
+ return bg_fp64_radians_normalize(angle, range);
+}
+
+#endif
diff --git a/basic-geometry/basic-geometry.cbp b/basic-geometry/basic-geometry.cbp
new file mode 100644
index 0000000..b86b9f1
--- /dev/null
+++ b/basic-geometry/basic-geometry.cbp
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/basic-geometry/basic-geometry.h b/basic-geometry/basic-geometry.h
new file mode 100644
index 0000000..80740bb
--- /dev/null
+++ b/basic-geometry/basic-geometry.h
@@ -0,0 +1,22 @@
+#ifndef __GEOMETRY_H__
+#define __GEOMETRY_H__
+
+#include "basis.h"
+
+#include "angle.h"
+
+#include "vector2.h"
+#include "vector3.h"
+
+#include "matrixes.h"
+#include "matrix2x2.h"
+#include "matrix2x3.h"
+#include "matrix3x2.h"
+#include "matrix3x3.h"
+
+#include "rotation3.h"
+
+#include "quaternion.h"
+#include "versor.h"
+
+#endif
diff --git a/basic-geometry/basic-geometry.vcxproj b/basic-geometry/basic-geometry.vcxproj
new file mode 100644
index 0000000..fdc6f21
--- /dev/null
+++ b/basic-geometry/basic-geometry.vcxproj
@@ -0,0 +1,181 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ x64
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 16.0
+ Win32Proj
+ {40ca6fb4-135f-4d54-a8d9-7338ba56e6a7}
+ basic-geometry
+ 10.0
+
+
+
+ StaticLibrary
+ true
+ v143
+ Unicode
+
+
+ StaticLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+ StaticLibrary
+ true
+ v143
+ Unicode
+
+
+ StaticLibrary
+ false
+ v143
+ true
+ Unicode
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+ true
+
+
+ false
+
+
+
+ Level3
+ true
+ WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ NotUsing
+
+
+
+
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ NotUsing
+
+
+
+
+ true
+ true
+ true
+
+
+
+
+ Level3
+ true
+ _DEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ NotUsing
+
+
+
+
+ true
+
+
+
+
+ Level3
+ true
+ true
+ true
+ NDEBUG;_LIB;%(PreprocessorDefinitions)
+ true
+ NotUsing
+
+
+
+
+ true
+ true
+ true
+
+
+
+
+
+
\ No newline at end of file
diff --git a/basic-geometry/basic-geometry.vcxproj.filters b/basic-geometry/basic-geometry.vcxproj.filters
new file mode 100644
index 0000000..9a1b6d4
--- /dev/null
+++ b/basic-geometry/basic-geometry.vcxproj.filters
@@ -0,0 +1,96 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+ Файлы заголовков
+
+
+ Файлы заголовков
+
+
+ Файлы заголовков
+
+
+ Файлы заголовков
+
+
+ Файлы заголовков
+
+
+ Файлы заголовков
+
+
+ Файлы заголовков
+
+
+ Файлы заголовков
+
+
+ Файлы заголовков
+
+
+ Файлы заголовков
+
+
+ Файлы заголовков
+
+
+ Файлы заголовков
+
+
+ Файлы заголовков
+
+
+
+
+ Исходные файлы
+
+
+ Исходные файлы
+
+
+ Исходные файлы
+
+
+ Исходные файлы
+
+
+ Исходные файлы
+
+
+ Исходные файлы
+
+
+ Исходные файлы
+
+
+ Исходные файлы
+
+
+ Исходные файлы
+
+
+ Исходные файлы
+
+
+ Исходные файлы
+
+
+ Исходные файлы
+
+
+
\ No newline at end of file
diff --git a/basic-geometry/basis.c b/basic-geometry/basis.c
new file mode 100644
index 0000000..03a9af7
--- /dev/null
+++ b/basic-geometry/basis.c
@@ -0,0 +1,2 @@
+#include "basis.h"
+
diff --git a/basic-geometry/basis.h b/basic-geometry/basis.h
new file mode 100644
index 0000000..26528cf
--- /dev/null
+++ b/basic-geometry/basis.h
@@ -0,0 +1,56 @@
+#ifndef __GEOMETRY__TYPES_H_
+#define __GEOMETRY__TYPES_H_
+
+#define BG_FP32_EPSYLON_EFFECTIVENESS_LIMIT 10.0f
+
+#define BG_FP32_EPSYLON 5E-7f
+#define BG_FP32_TWO_EPSYLON 1E-6f
+#define BG_FP32_SQUARE_EPSYLON 2.5E-13f
+
+#define BG_FP32_ONE_THIRD 0.333333333f
+#define BG_FP32_ONE_SIXTH 0.166666667f
+#define BG_FP32_ONE_NINETH 0.111111111f
+
+#define BG_FP32_GOLDEN_RATIO_HIGH 1.618034f
+#define BG_FP32_GOLDEN_RATIO_LOW 0.618034f
+
+#define BG_FP64_EPSYLON_EFFECTIVENESS_LIMIT 10.0
+
+#define BG_FP64_EPSYLON 5E-14
+#define BG_FP64_TWO_EPSYLON 1E-13
+#define BG_FP64_SQUARE_EPSYLON 2.5E-27
+
+#define BG_FP64_ONE_THIRD 0.333333333333333333
+#define BG_FP64_ONE_SIXTH 0.166666666666666667
+#define BG_FP64_ONE_NINETH 0.111111111111111111
+
+#define BG_FP64_GOLDEN_RATIO_HIGH 1.61803398874989485
+#define BG_FP64_GOLDEN_RATIO_LOW 0.61803398874989485
+
+static inline int bg_fp32_are_equal(const float value1, const float value2)
+{
+ if (-BG_FP32_EPSYLON_EFFECTIVENESS_LIMIT < value1 && value1 < BG_FP32_EPSYLON_EFFECTIVENESS_LIMIT) {
+ return -BG_FP32_EPSYLON <= (value1 - value2) && (value1 - value2) <= BG_FP32_EPSYLON;
+ }
+
+ if (value1 < 0.0f) {
+ return (1.0f + BG_FP32_EPSYLON) * value2 <= value1 && (1.0f + BG_FP32_EPSYLON) * value1 <= value2;
+ }
+
+ return value2 <= value1 * (1.0f + BG_FP32_EPSYLON) && value1 <= value2 * (1.0f + BG_FP32_EPSYLON);
+}
+
+static inline int bg_fp64_are_equal(const double value1, const double value2)
+{
+ if (-BG_FP64_EPSYLON_EFFECTIVENESS_LIMIT < value1 && value1 < BG_FP64_EPSYLON_EFFECTIVENESS_LIMIT) {
+ return -BG_FP64_EPSYLON <= (value1 - value2) && (value1 - value2) <= BG_FP64_EPSYLON;
+ }
+
+ if (value1 < 0.0) {
+ return (1.0 + BG_FP64_EPSYLON) * value2 <= value1 && (1.0 + BG_FP64_EPSYLON) * value1 <= value2;
+ }
+
+ return value2 <= value1 * (1.0 + BG_FP64_EPSYLON) && value1 <= value2 * (1.0 + BG_FP64_EPSYLON);
+}
+
+#endif
diff --git a/basic-geometry/geometry.h b/basic-geometry/geometry.h
new file mode 100644
index 0000000..80740bb
--- /dev/null
+++ b/basic-geometry/geometry.h
@@ -0,0 +1,22 @@
+#ifndef __GEOMETRY_H__
+#define __GEOMETRY_H__
+
+#include "basis.h"
+
+#include "angle.h"
+
+#include "vector2.h"
+#include "vector3.h"
+
+#include "matrixes.h"
+#include "matrix2x2.h"
+#include "matrix2x3.h"
+#include "matrix3x2.h"
+#include "matrix3x3.h"
+
+#include "rotation3.h"
+
+#include "quaternion.h"
+#include "versor.h"
+
+#endif
diff --git a/basic-geometry/matrix2x2.c b/basic-geometry/matrix2x2.c
new file mode 100644
index 0000000..4bf7977
--- /dev/null
+++ b/basic-geometry/matrix2x2.c
@@ -0,0 +1 @@
+#include "matrix2x2.h"
diff --git a/basic-geometry/matrix2x2.h b/basic-geometry/matrix2x2.h
new file mode 100644
index 0000000..70f8c91
--- /dev/null
+++ b/basic-geometry/matrix2x2.h
@@ -0,0 +1,488 @@
+#ifndef _GEOMETRY_MATRIX2X2_H_
+#define _GEOMETRY_MATRIX2X2_H_
+
+#include "angle.h"
+#include "vector2.h"
+#include "matrixes.h"
+
+// =================== Reset ==================== //
+
+static inline void bg_fp32_matrix2x2_reset(BgFP32Matrix2x2* matrix)
+{
+ matrix->r1c1 = 0.0f;
+ matrix->r1c2 = 0.0f;
+ matrix->r2c1 = 0.0f;
+ matrix->r2c2 = 0.0f;
+}
+
+static inline void bg_fp64_matrix2x2_reset(BgFP64Matrix2x2* matrix)
+{
+ matrix->r1c1 = 0.0;
+ matrix->r1c2 = 0.0;
+ matrix->r2c1 = 0.0;
+ matrix->r2c2 = 0.0;
+}
+
+// ================== Identity ================== //
+
+static inline void bg_fp32_matrix2x2_set_to_identity(BgFP32Matrix2x2* matrix)
+{
+ matrix->r1c1 = 1.0f;
+ matrix->r1c2 = 0.0f;
+ matrix->r2c1 = 0.0f;
+ matrix->r2c2 = 1.0f;
+}
+
+static inline void bg_fp64_matrix2x2_set_to_identity(BgFP64Matrix2x2* matrix)
+{
+ matrix->r1c1 = 1.0;
+ matrix->r1c2 = 0.0;
+ matrix->r2c1 = 0.0;
+ matrix->r2c2 = 1.0;
+}
+
+// ================ Make Diagonal =============== //
+
+static inline void bg_fp32_matrix2x2_set_to_diagonal(const float d1, const float d2, BgFP32Matrix2x2* matrix)
+{
+ matrix->r1c1 = d1;
+ matrix->r1c2 = 0.0f;
+ matrix->r2c1 = 0.0f;
+ matrix->r2c2 = d2;
+}
+
+static inline void bg_fp64_matrix2x2_set_to_diagonal(const double d1, const double d2, BgFP64Matrix2x2* matrix)
+{
+ matrix->r1c1 = d1;
+ matrix->r1c2 = 0.0;
+ matrix->r2c1 = 0.0;
+ matrix->r2c2 = d2;
+}
+
+// ============== Rotation Matrix =============== //
+
+static inline void bg_fp32_matrix2x2_make_turn(const float angle, const angle_unit_t unit, BgFP32Matrix2x2* matrix)
+{
+ const float radians = bg_fp32_angle_to_radians(angle, unit);
+ const float cosine = cosf(radians);
+ const float sine = sinf(radians);
+
+ matrix->r1c1 = cosine;
+ matrix->r1c2 = -sine;
+ matrix->r2c1 = sine;
+ matrix->r2c2 = cosine;
+}
+
+static inline void bg_fp64_matrix2x2_make_turn(const double angle, const angle_unit_t unit, BgFP64Matrix2x2* matrix)
+{
+ const double radians = bg_fp64_angle_to_radians(angle, unit);
+ const double cosine = cos(radians);
+ const double sine = sin(radians);
+
+ matrix->r1c1 = cosine;
+ matrix->r1c2 = -sine;
+ matrix->r2c1 = sine;
+ matrix->r2c2 = cosine;
+}
+
+// ==================== Copy ==================== //
+
+static inline void bg_fp32_matrix2x2_copy(const BgFP32Matrix2x2* from, BgFP32Matrix2x2* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r1c2;
+
+ to->r2c1 = from->r2c1;
+ to->r2c2 = from->r2c2;
+}
+
+static inline void bg_fp64_matrix2x2_copy(const BgFP64Matrix2x2* from, BgFP64Matrix2x2* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r1c2;
+
+ to->r2c1 = from->r2c1;
+ to->r2c2 = from->r2c2;
+}
+
+// ============= Copy to twin type ============== //
+
+static inline void bg_fp32_matrix2x2_set_from_fp64(const BgFP64Matrix2x2* from, BgFP32Matrix2x2* to)
+{
+ to->r1c1 = (float)from->r1c1;
+ to->r1c2 = (float)from->r1c2;
+
+ to->r2c1 = (float)from->r2c1;
+ to->r2c2 = (float)from->r2c2;
+}
+
+static inline void bg_fp64_matrix2x2_set_from_fp32(const BgFP32Matrix2x2* from, BgFP64Matrix2x2* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r1c2;
+
+ to->r2c1 = from->r2c1;
+ to->r2c2 = from->r2c2;
+}
+
+// ================ Determinant ================= //
+
+static inline float bg_fp32_matrix2x2_get_determinant(const BgFP32Matrix2x2* matrix)
+{
+ return matrix->r1c1 * matrix->r2c2 - matrix->r1c2 * matrix->r2c1;
+}
+
+static inline double bg_fp64_matrix2x2_get_determinant(const BgFP64Matrix2x2* matrix)
+{
+ return matrix->r1c1 * matrix->r2c2 - matrix->r1c2 * matrix->r2c1;
+}
+
+// ================== Singular ================== //
+
+static inline int bg_fp32_matrix2x2_is_singular(const BgFP32Matrix2x2* matrix)
+{
+ const float determinant = bg_fp32_matrix2x2_get_determinant(matrix);
+
+ return -BG_FP32_EPSYLON <= determinant && determinant <= BG_FP32_EPSYLON;
+}
+
+static inline int bg_fp64_matrix2x2_is_singular(const BgFP64Matrix2x2* matrix)
+{
+ const double determinant = bg_fp64_matrix2x2_get_determinant(matrix);
+
+ return -BG_FP64_EPSYLON <= determinant && determinant <= BG_FP64_EPSYLON;
+}
+
+// =============== Transposition ================ //
+
+static inline void bg_fp32_matrix2x2_transpose(BgFP32Matrix2x2* matrix)
+{
+ const float tmp = matrix->r1c2;
+ matrix->r1c2 = matrix->r2c1;
+ matrix->r2c1 = tmp;
+}
+
+static inline void bg_fp64_matrix2x2_transpose(BgFP64Matrix2x2* matrix)
+{
+ const double tmp = matrix->r1c2;
+ matrix->r1c2 = matrix->r2c1;
+ matrix->r2c1 = tmp;
+}
+
+// ================= Inversion ================== //
+
+static inline int bg_fp32_matrix2x2_invert(BgFP32Matrix2x2* matrix)
+{
+ const float determinant = bg_fp32_matrix2x2_get_determinant(matrix);
+
+ if (-BG_FP32_EPSYLON <= determinant && determinant <= BG_FP32_EPSYLON) {
+ return 0;
+ }
+
+ const float r1c1 = matrix->r2c2;
+ const float r1c2 = -matrix->r1c2;
+
+ const float r2c1 = -matrix->r2c1;
+ const float r2c2 = matrix->r1c1;
+
+ matrix->r1c1 = r1c1 / determinant;
+ matrix->r1c2 = r1c2 / determinant;
+
+ matrix->r2c1 = r2c1 / determinant;
+ matrix->r2c2 = r2c2 / determinant;
+
+ return 1;
+}
+
+static inline int bg_fp64_matrix2x2_invert(BgFP64Matrix2x2* matrix)
+{
+ const double determinant = bg_fp64_matrix2x2_get_determinant(matrix);
+
+ if (-BG_FP64_EPSYLON <= determinant && determinant <= BG_FP64_EPSYLON) {
+ return 0;
+ }
+
+ const double r1c1 = matrix->r2c2;
+ const double r1c2 = -matrix->r1c2;
+
+ const double r2c1 = -matrix->r2c1;
+ const double r2c2 = matrix->r1c1;
+
+ matrix->r1c1 = r1c1 / determinant;
+ matrix->r1c2 = r1c2 / determinant;
+
+ matrix->r2c1 = r2c1 / determinant;
+ matrix->r2c2 = r2c2 / determinant;
+
+ return 1;
+}
+
+// =============== Set Transposed =============== //
+
+static inline void bg_fp32_matrix2x2_set_transposed(const BgFP32Matrix2x2* from, BgFP32Matrix2x2* to)
+{
+ float tmp = from->r1c2;
+
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r2c1;
+
+ to->r2c1 = tmp;
+ to->r2c2 = from->r2c2;
+}
+
+static inline void bg_fp64_matrix2x2_set_transposed(const BgFP64Matrix2x2* from, BgFP64Matrix2x2* to)
+{
+ double tmp = from->r1c2;
+
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r2c1;
+
+ to->r2c1 = tmp;
+ to->r2c2 = from->r2c2;
+}
+
+// ================ Set Inverted ================ //
+
+static inline int bg_fp32_matrix2x2_set_inverted(const BgFP32Matrix2x2* from, BgFP32Matrix2x2* to)
+{
+ const float determinant = bg_fp32_matrix2x2_get_determinant(from);
+
+ if (-BG_FP32_EPSYLON <= determinant && determinant <= BG_FP32_EPSYLON) {
+ return 0;
+ }
+
+ const float r1c1 = from->r2c2;
+ const float r1c2 = -from->r1c2;
+
+ const float r2c1 = -from->r2c1;
+ const float r2c2 = from->r1c1;
+
+ to->r1c1 = r1c1 / determinant;
+ to->r1c2 = r1c2 / determinant;
+
+ to->r2c1 = r2c1 / determinant;
+ to->r2c2 = r2c2 / determinant;
+
+ return 1;
+}
+
+static inline int bg_fp64_matrix2x2_set_inverted(const BgFP64Matrix2x2* from, BgFP64Matrix2x2* to)
+{
+ const double determinant = bg_fp64_matrix2x2_get_determinant(from);
+
+ if (-BG_FP64_EPSYLON <= determinant && determinant <= BG_FP64_EPSYLON) {
+ return 0;
+ }
+
+ const double r1c1 = from->r2c2;
+ const double r1c2 = -from->r1c2;
+
+ const double r2c1 = -from->r2c1;
+ const double r2c2 = from->r1c1;
+
+ to->r1c1 = r1c1 / determinant;
+ to->r1c2 = r1c2 / determinant;
+
+ to->r2c1 = r2c1 / determinant;
+ to->r2c2 = r2c2 / determinant;
+
+ return 1;
+}
+
+// ================= Set Row 1 ================== //
+
+static inline void bg_fp32_matrix2x2_set_row1(const float c1, const float c2, BgFP32Matrix2x2* matrix)
+{
+ matrix->r1c1 = c1;
+ matrix->r1c2 = c2;
+}
+
+static inline void bg_fp64_matrix2x2_set_row1(const double c1, const double c2, BgFP64Matrix2x2* matrix)
+{
+ matrix->r1c1 = c1;
+ matrix->r1c2 = c2;
+}
+
+// ================= Set Row 2 ================== //
+
+static inline void bg_fp32_matrix2x2_set_row2(const float c1, const float c2, BgFP32Matrix2x2* matrix)
+{
+ matrix->r2c1 = c1;
+ matrix->r2c2 = c2;
+}
+
+static inline void bg_fp64_matrix2x2_set_row2(const double c1, const double c2, BgFP64Matrix2x2* matrix)
+{
+ matrix->r2c1 = c1;
+ matrix->r2c2 = c2;
+}
+
+// ================ Set Column 1 ================ //
+
+static inline void bg_fp32_matrix2x2_set_column1(const float r1, const float r2, BgFP32Matrix2x2* matrix)
+{
+ matrix->r1c1 = r1;
+ matrix->r2c1 = r2;
+}
+
+static inline void bg_fp64_matrix2x2_set_column1(const double r1, const double r2, BgFP64Matrix2x2* matrix)
+{
+ matrix->r1c1 = r1;
+ matrix->r2c1 = r2;
+}
+
+// ================ Set Column 2 ================ //
+
+static inline void bg_fp32_matrix2x2_set_column2(const float r1, const float r2, BgFP32Matrix2x2* matrix)
+{
+ matrix->r1c2 = r1;
+ matrix->r2c2 = r2;
+}
+
+static inline void bg_fp64_matrix2x2_set_column2(const double r1, const double r2, BgFP64Matrix2x2* matrix)
+{
+ matrix->r1c2 = r1;
+ matrix->r2c2 = r2;
+}
+
+// ================ Append scaled =============== //
+
+static inline void bg_fp32_matrix2x2_append_scaled(BgFP32Matrix2x2* basic_vector, const BgFP32Matrix2x2* scalable_vector, const float scale)
+{
+ basic_vector->r1c1 += scalable_vector->r1c1 * scale;
+ basic_vector->r1c2 += scalable_vector->r1c2 * scale;
+
+ basic_vector->r2c1 += scalable_vector->r2c1 * scale;
+ basic_vector->r2c2 += scalable_vector->r2c2 * scale;
+}
+
+static inline void bg_fp64_matrix2x2_append_scaled(BgFP64Matrix2x2* basic_vector, const BgFP64Matrix2x2* scalable_vector, const double scale)
+{
+ basic_vector->r1c1 += scalable_vector->r1c1 * scale;
+ basic_vector->r1c2 += scalable_vector->r1c2 * scale;
+
+ basic_vector->r2c1 += scalable_vector->r2c1 * scale;
+ basic_vector->r2c2 += scalable_vector->r2c2 * scale;
+}
+
+// ================== Addition ================== //
+
+static inline void bg_fp32_matrix2x2_add(const BgFP32Matrix2x2* matrix1, const BgFP32Matrix2x2* matrix2, BgFP32Matrix2x2* sum)
+{
+ sum->r1c1 = matrix1->r1c1 + matrix2->r1c1;
+ sum->r1c2 = matrix1->r1c2 + matrix2->r1c2;
+
+ sum->r2c1 = matrix1->r2c1 + matrix2->r2c1;
+ sum->r2c2 = matrix1->r2c2 + matrix2->r2c2;
+}
+
+static inline void bg_fp64_matrix2x2_add(const BgFP64Matrix2x2* matrix1, const BgFP64Matrix2x2* matrix2, BgFP64Matrix2x2* sum)
+{
+ sum->r1c1 = matrix1->r1c1 + matrix2->r1c1;
+ sum->r1c2 = matrix1->r1c2 + matrix2->r1c2;
+
+ sum->r2c1 = matrix1->r2c1 + matrix2->r2c1;
+ sum->r2c2 = matrix1->r2c2 + matrix2->r2c2;
+}
+
+// ================ Subtraction ================= //
+
+static inline void bg_fp32_matrix2x2_subtract(const BgFP32Matrix2x2* minuend, const BgFP32Matrix2x2* subtrahend, BgFP32Matrix2x2* difference)
+{
+ difference->r1c1 = minuend->r1c1 - subtrahend->r1c1;
+ difference->r1c2 = minuend->r1c2 - subtrahend->r1c2;
+
+ difference->r2c1 = minuend->r2c1 - subtrahend->r2c1;
+ difference->r2c2 = minuend->r2c2 - subtrahend->r2c2;
+}
+
+static inline void bg_fp64_matrix2x2_subtract(const BgFP64Matrix2x2* minuend, const BgFP64Matrix2x2* subtrahend, BgFP64Matrix2x2* difference)
+{
+ difference->r1c1 = minuend->r1c1 - subtrahend->r1c1;
+ difference->r1c2 = minuend->r1c2 - subtrahend->r1c2;
+
+ difference->r2c1 = minuend->r2c1 - subtrahend->r2c1;
+ difference->r2c2 = minuend->r2c2 - subtrahend->r2c2;
+}
+
+// =============== Multiplication =============== //
+
+static inline void bg_fp32_matrix2x2_multiply(const BgFP32Matrix2x2* multiplicand, const float multiplier, BgFP32Matrix2x2* product)
+{
+ product->r1c1 = multiplicand->r1c1 * multiplier;
+ product->r1c2 = multiplicand->r1c2 * multiplier;
+
+ product->r2c1 = multiplicand->r2c1 * multiplier;
+ product->r2c2 = multiplicand->r2c2 * multiplier;
+}
+
+static inline void bg_fp64_matrix2x2_multiply(const BgFP64Matrix2x2* multiplicand, const double multiplier, BgFP64Matrix2x2* product)
+{
+ product->r1c1 = multiplicand->r1c1 * multiplier;
+ product->r1c2 = multiplicand->r1c2 * multiplier;
+
+ product->r2c1 = multiplicand->r2c1 * multiplier;
+ product->r2c2 = multiplicand->r2c2 * multiplier;
+}
+
+// ================== Division ================== //
+
+static inline void bg_fp32_matrix2x2_divide(const BgFP32Matrix2x2* dividend, const float divisor, BgFP32Matrix2x2* quotient)
+{
+ quotient->r1c1 = dividend->r1c1 / divisor;
+ quotient->r1c2 = dividend->r1c2 / divisor;
+
+ quotient->r2c1 = dividend->r2c1 / divisor;
+ quotient->r2c2 = dividend->r2c2 / divisor;
+}
+
+static inline void bg_fp64_matrix2x2_divide(const BgFP64Matrix2x2* dividend, const double divisor, BgFP64Matrix2x2* quotient)
+{
+ quotient->r1c1 = dividend->r1c1 / divisor;
+ quotient->r1c2 = dividend->r1c2 / divisor;
+
+ quotient->r2c1 = dividend->r2c1 / divisor;
+ quotient->r2c2 = dividend->r2c2 / divisor;
+}
+
+// ============ Left Vector Product ============= //
+
+static inline void bg_fp32_matrix2x2_left_product(const BgFP32Vector2* vector, const BgFP32Matrix2x2* matrix, BgFP32Vector2* result)
+{
+ bg_fp32_vector2_set_values(
+ vector->x1 * matrix->r1c1 + vector->x2 * matrix->r2c1,
+ vector->x1 * matrix->r1c2 + vector->x2 * matrix->r2c2,
+ result
+ );
+}
+
+static inline void bg_fp64_matrix2x2_left_product(const BgFP64Vector2* vector, const BgFP64Matrix2x2* matrix, BgFP64Vector2* result)
+{
+ bg_fp64_vector2_set_values(
+ vector->x1 * matrix->r1c1 + vector->x2 * matrix->r2c1,
+ vector->x1 * matrix->r1c2 + vector->x2 * matrix->r2c2,
+ result
+ );
+}
+
+// ============ Right Vector Product ============ //
+
+static inline void bg_fp32_matrix2x2_right_product(const BgFP32Matrix2x2* matrix, const BgFP32Vector2* vector, BgFP32Vector2* result)
+{
+ bg_fp32_vector2_set_values(
+ matrix->r1c1 * vector->x1 + matrix->r1c2 * vector->x2,
+ matrix->r2c1 * vector->x1 + matrix->r2c2 * vector->x2,
+ result
+ );
+}
+
+static inline void bg_fp64_matrix2x2_right_product(const BgFP64Matrix2x2* matrix, const BgFP64Vector2* vector, BgFP64Vector2* result)
+{
+ bg_fp64_vector2_set_values(
+ matrix->r1c1 * vector->x1 + matrix->r1c2 * vector->x2,
+ matrix->r2c1 * vector->x1 + matrix->r2c2 * vector->x2,
+ result
+ );
+}
+
+#endif
diff --git a/basic-geometry/matrix2x3.c b/basic-geometry/matrix2x3.c
new file mode 100644
index 0000000..95b9a26
--- /dev/null
+++ b/basic-geometry/matrix2x3.c
@@ -0,0 +1,2 @@
+#include "matrix2x3.h"
+
diff --git a/basic-geometry/matrix2x3.h b/basic-geometry/matrix2x3.h
new file mode 100644
index 0000000..ee3d3d7
--- /dev/null
+++ b/basic-geometry/matrix2x3.h
@@ -0,0 +1,372 @@
+#ifndef _GEOMETRY_MATRIX2X3_H_
+#define _GEOMETRY_MATRIX2X3_H_
+
+#include "vector2.h"
+#include "vector3.h"
+#include "matrixes.h"
+
+// =================== Reset ==================== //
+
+static inline void bg_fp32_matrix2x3_reset(BgFP32Matrix2x3* matrix)
+{
+ matrix->r1c1 = 0.0f;
+ matrix->r1c2 = 0.0f;
+
+ matrix->r2c1 = 0.0f;
+ matrix->r2c2 = 0.0f;
+
+ matrix->r3c1 = 0.0f;
+ matrix->r3c2 = 0.0f;
+}
+
+static inline void bg_fp64_matrix2x3_reset(BgFP64Matrix2x3* matrix)
+{
+ matrix->r1c1 = 0.0;
+ matrix->r1c2 = 0.0;
+
+ matrix->r2c1 = 0.0;
+ matrix->r2c2 = 0.0;
+
+ matrix->r3c1 = 0.0;
+ matrix->r3c2 = 0.0;
+}
+
+// ==================== Copy ==================== //
+
+static inline void bg_fp32_matrix2x3_copy(const BgFP32Matrix2x3* from, BgFP32Matrix2x3* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r1c2;
+
+ to->r2c1 = from->r2c1;
+ to->r2c2 = from->r2c2;
+
+ to->r3c1 = from->r3c1;
+ to->r3c2 = from->r3c2;
+}
+
+static inline void bg_fp64_matrix2x3_copy(const BgFP64Matrix2x3* from, BgFP64Matrix2x3* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r1c2;
+
+ to->r2c1 = from->r2c1;
+ to->r2c2 = from->r2c2;
+
+ to->r3c1 = from->r3c1;
+ to->r3c2 = from->r3c2;
+}
+
+// ============= Copy to twin type ============== //
+
+static inline void bg_fp32_matrix2x3_set_from_fp64(const BgFP64Matrix2x3* from, BgFP32Matrix2x3* to)
+{
+ to->r1c1 = (float) from->r1c1;
+ to->r1c2 = (float) from->r1c2;
+
+ to->r2c1 = (float) from->r2c1;
+ to->r2c2 = (float) from->r2c2;
+
+ to->r3c1 = (float) from->r3c1;
+ to->r3c2 = (float) from->r3c2;
+}
+
+static inline void bg_fp64_matrix2x3_set_from_fp32(const BgFP32Matrix2x3* from, BgFP64Matrix2x3* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r1c2;
+
+ to->r2c1 = from->r2c1;
+ to->r2c2 = from->r2c2;
+
+ to->r3c1 = from->r3c1;
+ to->r3c2 = from->r3c2;
+}
+
+// =============== Set transposed =============== //
+
+static inline void bg_fp32_matrix2x3_set_transposed(const BgFP32Matrix3x2* from, BgFP32Matrix2x3* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r2c1;
+
+ to->r2c1 = from->r1c2;
+ to->r2c2 = from->r2c2;
+
+ to->r3c1 = from->r1c3;
+ to->r3c2 = from->r2c3;
+}
+
+static inline void bg_fp64_matrix2x3_set_transposed(const BgFP64Matrix3x2* from, BgFP64Matrix2x3* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r2c1;
+
+ to->r2c1 = from->r1c2;
+ to->r2c2 = from->r2c2;
+
+ to->r3c1 = from->r1c3;
+ to->r3c2 = from->r2c3;
+}
+
+// =============== Set transposed =============== //
+
+static inline void bg_fp32_matrix2x3_set_transposed_fp64(const BgFP64Matrix3x2* from, BgFP32Matrix2x3* to)
+{
+ to->r1c1 = (float) from->r1c1;
+ to->r1c2 = (float) from->r2c1;
+
+ to->r2c1 = (float) from->r1c2;
+ to->r2c2 = (float) from->r2c2;
+
+ to->r3c1 = (float) from->r1c3;
+ to->r3c2 = (float) from->r2c3;
+}
+
+static inline void bg_fp64_matrix2x3_set_transposed_fp32(const BgFP32Matrix3x2* from, BgFP64Matrix2x3* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r2c1;
+
+ to->r2c1 = from->r1c2;
+ to->r2c2 = from->r2c2;
+
+ to->r3c1 = from->r1c3;
+ to->r3c2 = from->r2c3;
+}
+
+// ================= Set Row 1 ================== //
+
+static inline void bg_fp32_matrix2x3_set_row1(const float c1, const float c2, BgFP32Matrix2x3* matrix)
+{
+ matrix->r1c1 = c1;
+ matrix->r1c2 = c2;
+}
+
+static inline void bg_fp64_matrix2x3_set_row1(const double c1, const double c2, BgFP64Matrix2x3* matrix)
+{
+ matrix->r1c1 = c1;
+ matrix->r1c2 = c2;
+}
+
+// ================= Set Row 2 ================== //
+
+static inline void bg_fp32_matrix2x3_set_row2(const float c1, const float c2, BgFP32Matrix2x3* matrix)
+{
+ matrix->r2c1 = c1;
+ matrix->r2c2 = c2;
+}
+
+static inline void bg_fp64_matrix2x3_set_row2(const double c1, const double c2, BgFP64Matrix2x3* matrix)
+{
+ matrix->r2c1 = c1;
+ matrix->r2c2 = c2;
+}
+
+// ================= Set Row 3 ================== //
+
+static inline void bg_fp32_matrix2x3_set_row3(const float c1, const float c2, BgFP32Matrix2x3* matrix)
+{
+ matrix->r3c1 = c1;
+ matrix->r3c2 = c2;
+}
+
+static inline void bg_fp64_matrix2x3_set_row3(const double c1, const double c2, BgFP64Matrix2x3* matrix)
+{
+ matrix->r3c1 = c1;
+ matrix->r3c2 = c2;
+}
+
+// ================ Set Column 1 ================ //
+
+static inline void bg_fp32_matrix2x3_set_column1(const float r1, const float r2, const float r3, BgFP32Matrix2x3* matrix)
+{
+ matrix->r1c1 = r1;
+ matrix->r2c1 = r2;
+ matrix->r3c1 = r3;
+}
+
+static inline void bg_fp64_matrix2x3_set_column1(const double r1, const double r2, const double r3, BgFP64Matrix2x3* matrix)
+{
+ matrix->r1c1 = r1;
+ matrix->r2c1 = r2;
+ matrix->r3c1 = r3;
+}
+
+// ================ Set Column 2 ================ //
+
+static inline void bg_fp32_matrix2x3_set_column2(const float r1, const float r2, const float r3, BgFP32Matrix2x3* matrix)
+{
+ matrix->r1c2 = r1;
+ matrix->r2c2 = r2;
+ matrix->r3c2 = r3;
+}
+
+static inline void bg_fp64_matrix2x3_set_column2(const double r1, const double r2, const double r3, BgFP64Matrix2x3* matrix)
+{
+ matrix->r1c2 = r1;
+ matrix->r2c2 = r2;
+ matrix->r3c2 = r3;
+}
+
+// ================ Append scaled =============== //
+
+static inline void bg_fp32_matrix2x3_append_scaled(BgFP32Matrix2x3* basic_vector, const BgFP32Matrix2x3* scalable_vector, const float scale)
+{
+ basic_vector->r1c1 += scalable_vector->r1c1 * scale;
+ basic_vector->r1c2 += scalable_vector->r1c2 * scale;
+
+ basic_vector->r2c1 += scalable_vector->r2c1 * scale;
+ basic_vector->r2c2 += scalable_vector->r2c2 * scale;
+
+ basic_vector->r3c1 += scalable_vector->r3c1 * scale;
+ basic_vector->r3c2 += scalable_vector->r3c2 * scale;
+}
+
+static inline void bg_fp64_matrix2x3_append_scaled(BgFP64Matrix2x3* basic_vector, const BgFP64Matrix2x3* scalable_vector, const double scale)
+{
+ basic_vector->r1c1 += scalable_vector->r1c1 * scale;
+ basic_vector->r1c2 += scalable_vector->r1c2 * scale;
+
+ basic_vector->r2c1 += scalable_vector->r2c1 * scale;
+ basic_vector->r2c2 += scalable_vector->r2c2 * scale;
+
+ basic_vector->r3c1 += scalable_vector->r3c1 * scale;
+ basic_vector->r3c2 += scalable_vector->r3c2 * scale;
+}
+
+// ================== Addition ================== //
+
+static inline void bg_fp32_matrix2x3_add(const BgFP32Matrix2x3* matrix1, const BgFP32Matrix2x3* matrix2, BgFP32Matrix2x3* sum)
+{
+ sum->r1c1 = matrix1->r1c1 + matrix2->r1c1;
+ sum->r1c2 = matrix1->r1c2 + matrix2->r1c2;
+
+ sum->r2c1 = matrix1->r2c1 + matrix2->r2c1;
+ sum->r2c2 = matrix1->r2c2 + matrix2->r2c2;
+
+ sum->r3c1 = matrix1->r3c1 + matrix2->r3c1;
+ sum->r3c2 = matrix1->r3c2 + matrix2->r3c2;
+}
+
+static inline void bg_fp64_matrix2x3_add(const BgFP64Matrix2x3* matrix1, const BgFP64Matrix2x3* matrix2, BgFP64Matrix2x3* sum)
+{
+ sum->r1c1 = matrix1->r1c1 + matrix2->r1c1;
+ sum->r1c2 = matrix1->r1c2 + matrix2->r1c2;
+
+ sum->r2c1 = matrix1->r2c1 + matrix2->r2c1;
+ sum->r2c2 = matrix1->r2c2 + matrix2->r2c2;
+
+ sum->r3c1 = matrix1->r3c1 + matrix2->r3c1;
+ sum->r3c2 = matrix1->r3c2 + matrix2->r3c2;
+}
+
+// ================ Subtraction ================= //
+
+static inline void bg_fp32_matrix2x3_subtract(const BgFP32Matrix2x3* minuend, const BgFP32Matrix2x3* subtrahend, BgFP32Matrix2x3* difference)
+{
+ difference->r1c1 = minuend->r1c1 - subtrahend->r1c1;
+ difference->r1c2 = minuend->r1c2 - subtrahend->r1c2;
+
+ difference->r2c1 = minuend->r2c1 - subtrahend->r2c1;
+ difference->r2c2 = minuend->r2c2 - subtrahend->r2c2;
+
+ difference->r3c1 = minuend->r3c1 - subtrahend->r3c1;
+ difference->r3c2 = minuend->r3c2 - subtrahend->r3c2;
+}
+
+static inline void bg_fp64_matrix2x3_subtract(const BgFP64Matrix2x3* minuend, const BgFP64Matrix2x3* subtrahend, BgFP64Matrix2x3* difference)
+{
+ difference->r1c1 = minuend->r1c1 - subtrahend->r1c1;
+ difference->r1c2 = minuend->r1c2 - subtrahend->r1c2;
+
+ difference->r2c1 = minuend->r2c1 - subtrahend->r2c1;
+ difference->r2c2 = minuend->r2c2 - subtrahend->r2c2;
+
+ difference->r3c1 = minuend->r3c1 - subtrahend->r3c1;
+ difference->r3c2 = minuend->r3c2 - subtrahend->r3c2;
+}
+
+// =============== Multiplication =============== //
+
+static inline void bg_fp32_matrix2x3_multiply(const BgFP32Matrix2x3* multiplicand, const float multiplier, BgFP32Matrix2x3* product)
+{
+ product->r1c1 = multiplicand->r1c1 * multiplier;
+ product->r1c2 = multiplicand->r1c2 * multiplier;
+
+ product->r2c1 = multiplicand->r2c1 * multiplier;
+ product->r2c2 = multiplicand->r2c2 * multiplier;
+
+ product->r3c1 = multiplicand->r3c1 * multiplier;
+ product->r3c2 = multiplicand->r3c2 * multiplier;
+}
+
+static inline void bg_fp64_matrix2x3_multiply(const BgFP64Matrix2x3* multiplicand, const double multiplier, BgFP64Matrix2x3* product)
+{
+ product->r1c1 = multiplicand->r1c1 * multiplier;
+ product->r1c2 = multiplicand->r1c2 * multiplier;
+
+ product->r2c1 = multiplicand->r2c1 * multiplier;
+ product->r2c2 = multiplicand->r2c2 * multiplier;
+
+ product->r3c1 = multiplicand->r3c1 * multiplier;
+ product->r3c2 = multiplicand->r3c2 * multiplier;
+}
+
+// ================== Division ================== //
+
+static inline void bg_fp32_matrix2x3_divide(const BgFP32Matrix2x3* dividend, const float divisor, BgFP32Matrix2x3* quotient)
+{
+ quotient->r1c1 = dividend->r1c1 / divisor;
+ quotient->r1c2 = dividend->r1c2 / divisor;
+
+ quotient->r2c1 = dividend->r2c1 / divisor;
+ quotient->r2c2 = dividend->r2c2 / divisor;
+
+ quotient->r3c1 = dividend->r3c1 / divisor;
+ quotient->r3c2 = dividend->r3c2 / divisor;
+}
+
+static inline void bg_fp64_matrix2x3_divide(const BgFP64Matrix2x3* dividend, const double divisor, BgFP64Matrix2x3* quotient)
+{
+ quotient->r1c1 = dividend->r1c1 / divisor;
+ quotient->r1c2 = dividend->r1c2 / divisor;
+
+ quotient->r2c1 = dividend->r2c1 / divisor;
+ quotient->r2c2 = dividend->r2c2 / divisor;
+
+ quotient->r3c1 = dividend->r3c1 / divisor;
+ quotient->r3c2 = dividend->r3c2 / divisor;
+}
+
+// ============ Left Vector Product ============= //
+
+static inline void bg_fp32_matrix2x3_left_product(const BgFP32Vector3* vector, const BgFP32Matrix2x3* matrix, BgFP32Vector2* result)
+{
+ result->x1 = vector->x1 * matrix->r1c1 + vector->x2 * matrix->r2c1 + vector->x3 * matrix->r3c1;
+ result->x2 = vector->x1 * matrix->r1c2 + vector->x2 * matrix->r2c2 + vector->x3 * matrix->r3c2;
+}
+
+static inline void bg_fp64_matrix2x3_left_product(const BgFP64Vector3* vector, const BgFP64Matrix2x3* matrix, BgFP64Vector2* result)
+{
+ result->x1 = vector->x1 * matrix->r1c1 + vector->x2 * matrix->r2c1 + vector->x3 * matrix->r3c1;
+ result->x2 = vector->x1 * matrix->r1c2 + vector->x2 * matrix->r2c2 + vector->x3 * matrix->r3c2;
+}
+
+// ============ Right Vector Product ============ //
+
+static inline void bg_fp32_matrix2x3_right_product(const BgFP32Matrix2x3* matrix, const BgFP32Vector2* vector, BgFP32Vector3* result)
+{
+ result->x1 = matrix->r1c1 * vector->x1 + matrix->r1c2 * vector->x2;
+ result->x2 = matrix->r2c1 * vector->x1 + matrix->r2c2 * vector->x2;
+ result->x3 = matrix->r3c1 * vector->x1 + matrix->r3c2 * vector->x2;
+}
+
+static inline void bg_fp64_matrix2x3_right_product(const BgFP64Matrix2x3* matrix, const BgFP64Vector2* vector, BgFP64Vector3* result)
+{
+ result->x1 = matrix->r1c1 * vector->x1 + matrix->r1c2 * vector->x2;
+ result->x2 = matrix->r2c1 * vector->x1 + matrix->r2c2 * vector->x2;
+ result->x3 = matrix->r3c1 * vector->x1 + matrix->r3c2 * vector->x2;
+}
+
+#endif
diff --git a/basic-geometry/matrix3x2.c b/basic-geometry/matrix3x2.c
new file mode 100644
index 0000000..71834ad
--- /dev/null
+++ b/basic-geometry/matrix3x2.c
@@ -0,0 +1,2 @@
+#include "matrix3x2.h"
+
diff --git a/basic-geometry/matrix3x2.h b/basic-geometry/matrix3x2.h
new file mode 100644
index 0000000..3aa48d5
--- /dev/null
+++ b/basic-geometry/matrix3x2.h
@@ -0,0 +1,328 @@
+#ifndef _GEOMETRY_MATRIX3X2_H_
+#define _GEOMETRY_MATRIX3X2_H_
+
+#include "vector2.h"
+#include "vector3.h"
+#include "matrixes.h"
+
+// =================== Reset ==================== //
+
+static inline void bg_fp32_matrix3x2_reset(BgFP32Matrix3x2* matrix)
+{
+ matrix->r1c1 = 0.0f;
+ matrix->r1c2 = 0.0f;
+ matrix->r1c3 = 0.0f;
+
+ matrix->r2c1 = 0.0f;
+ matrix->r2c2 = 0.0f;
+ matrix->r2c3 = 0.0f;
+}
+
+static inline void bg_fp64_matrix3x2_reset(BgFP64Matrix3x2* matrix)
+{
+ matrix->r1c1 = 0.0;
+ matrix->r1c2 = 0.0;
+ matrix->r1c3 = 0.0;
+
+ matrix->r2c1 = 0.0;
+ matrix->r2c2 = 0.0;
+ matrix->r2c3 = 0.0;
+}
+
+// ============= Set from twin type ============= //
+
+static inline void bg_fp32_matrix3x2_set_from_fp64(const BgFP64Matrix3x2* from, BgFP32Matrix3x2* to)
+{
+ to->r1c1 = (float) from->r1c1;
+ to->r1c2 = (float) from->r1c2;
+ to->r1c3 = (float) from->r1c3;
+
+ to->r2c1 = (float) from->r2c1;
+ to->r2c2 = (float) from->r2c2;
+ to->r2c3 = (float) from->r2c3;
+}
+
+static inline void bg_fp64_matrix3x2_set_from_fp32(const BgFP32Matrix3x2* from, BgFP64Matrix3x2* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r1c2;
+ to->r1c3 = from->r1c3;
+
+ to->r2c1 = from->r2c1;
+ to->r2c2 = from->r2c2;
+ to->r2c3 = from->r2c3;
+}
+
+// =============== Set transposed =============== //
+
+static inline void bg_fp32_matrix3x2_set_transposed(const BgFP32Matrix2x3* from, BgFP32Matrix3x2* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r2c1;
+ to->r1c3 = from->r3c1;
+
+ to->r2c1 = from->r1c2;
+ to->r2c2 = from->r2c2;
+ to->r2c3 = from->r3c2;
+}
+
+static inline void bg_fp64_matrix3x2_set_transposed(const BgFP64Matrix2x3* from, BgFP64Matrix3x2* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r2c1;
+ to->r1c3 = from->r3c1;
+
+ to->r2c1 = from->r1c2;
+ to->r2c2 = from->r2c2;
+ to->r2c3 = from->r3c2;
+}
+
+// =============== Set transposed =============== //
+
+static inline void bg_fp32_matrix3x2_set_transposed_fp64(const BgFP64Matrix2x3* from, BgFP32Matrix3x2* to)
+{
+ to->r1c1 = (float) from->r1c1;
+ to->r1c2 = (float) from->r2c1;
+ to->r1c3 = (float) from->r3c1;
+
+ to->r2c1 = (float) from->r1c2;
+ to->r2c2 = (float) from->r2c2;
+ to->r2c3 = (float) from->r3c2;
+}
+
+static inline void bg_fp64_matrix3x2_set_transposed_fp32(const BgFP32Matrix2x3* from, BgFP64Matrix3x2* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r2c1;
+ to->r1c3 = from->r3c1;
+
+ to->r2c1 = from->r1c2;
+ to->r2c2 = from->r2c2;
+ to->r2c3 = from->r3c2;
+}
+
+// ================= Set Row 1 ================== //
+
+static inline void bg_fp32_matrix3x2_set_row1(const float c1, const float c2, const float c3, BgFP32Matrix3x2* matrix)
+{
+ matrix->r1c1 = c1;
+ matrix->r1c2 = c2;
+ matrix->r1c3 = c3;
+}
+
+static inline void bg_fp64_matrix3x2_set_row1(const double c1, const double c2, const double c3, BgFP64Matrix3x2* matrix)
+{
+ matrix->r1c1 = c1;
+ matrix->r1c2 = c2;
+ matrix->r1c3 = c3;
+}
+
+// ================= Set Row 2 ================== //
+
+static inline void bg_fp32_matrix3x2_set_row2(const float c1, const float c2, const float c3, BgFP32Matrix3x2* matrix)
+{
+ matrix->r2c1 = c1;
+ matrix->r2c2 = c2;
+ matrix->r2c3 = c3;
+}
+
+static inline void bg_fp64_matrix3x2_set_row2(const double c1, const double c2, const double c3, BgFP64Matrix3x2* matrix)
+{
+ matrix->r2c1 = c1;
+ matrix->r2c2 = c2;
+ matrix->r2c3 = c3;
+}
+
+// ================ Set Column 1 ================ //
+
+static inline void bg_fp32_matrix3x2_set_column1(const float r1, const float r2, BgFP32Matrix3x2* matrix)
+{
+ matrix->r1c1 = r1;
+ matrix->r2c1 = r2;
+}
+
+static inline void bg_fp64_matrix3x2_set_column1(const double r1, const double r2, BgFP64Matrix3x2* matrix)
+{
+ matrix->r1c1 = r1;
+ matrix->r2c1 = r2;
+}
+
+// ================ Set Column 2 ================ //
+
+static inline void bg_fp32_matrix3x2_set_column2(const float r1, const float r2, BgFP32Matrix3x2* matrix)
+{
+ matrix->r1c2 = r1;
+ matrix->r2c2 = r2;
+}
+
+static inline void bg_fp64_matrix3x2_set_column2(const double r1, const double r2, BgFP64Matrix3x2* matrix)
+{
+ matrix->r1c2 = r1;
+ matrix->r2c2 = r2;
+}
+
+// ================ Set Column 3 ================ //
+
+static inline void bg_fp32_matrix3x2_set_column3(const float r1, const float r2, BgFP32Matrix3x2* matrix)
+{
+ matrix->r1c3 = r1;
+ matrix->r2c3 = r2;
+}
+
+static inline void bg_fp64_matrix3x2_set_column3(const double r1, const double r2, BgFP64Matrix3x2* matrix)
+{
+ matrix->r1c3 = r1;
+ matrix->r2c3 = r2;
+}
+
+// ================ Append scaled =============== //
+
+static inline void bg_fp32_matrix3x2_append_scaled(BgFP32Matrix3x2* basic_vector, const BgFP32Matrix3x2* scalable_vector, const float scale)
+{
+ basic_vector->r1c1 += scalable_vector->r1c1 * scale;
+ basic_vector->r1c2 += scalable_vector->r1c2 * scale;
+ basic_vector->r1c3 += scalable_vector->r1c3 * scale;
+
+ basic_vector->r2c1 += scalable_vector->r2c1 * scale;
+ basic_vector->r2c2 += scalable_vector->r2c2 * scale;
+ basic_vector->r2c3 += scalable_vector->r2c3 * scale;
+}
+
+static inline void bg_fp64_matrix3x2_append_scaled(BgFP64Matrix3x2* basic_vector, const BgFP64Matrix3x2* scalable_vector, const double scale)
+{
+ basic_vector->r1c1 += scalable_vector->r1c1 * scale;
+ basic_vector->r1c2 += scalable_vector->r1c2 * scale;
+ basic_vector->r1c3 += scalable_vector->r1c3 * scale;
+
+ basic_vector->r2c1 += scalable_vector->r2c1 * scale;
+ basic_vector->r2c2 += scalable_vector->r2c2 * scale;
+ basic_vector->r2c3 += scalable_vector->r2c3 * scale;
+}
+
+// ================== Addition ================== //
+
+static inline void bg_fp32_matrix3x2_add(const BgFP32Matrix3x2* matrix1, const BgFP32Matrix3x2* matrix2, BgFP32Matrix3x2* sum)
+{
+ sum->r1c1 = matrix1->r1c1 + matrix2->r1c1;
+ sum->r1c2 = matrix1->r1c2 + matrix2->r1c2;
+ sum->r1c3 = matrix1->r1c3 + matrix2->r1c3;
+
+ sum->r2c1 = matrix1->r2c1 + matrix2->r2c1;
+ sum->r2c2 = matrix1->r2c2 + matrix2->r2c2;
+ sum->r2c3 = matrix1->r2c3 + matrix2->r2c3;
+}
+
+static inline void bg_fp64_matrix3x2_add(const BgFP64Matrix3x2* matrix1, const BgFP64Matrix3x2* matrix2, BgFP64Matrix3x2* sum)
+{
+ sum->r1c1 = matrix1->r1c1 + matrix2->r1c1;
+ sum->r1c2 = matrix1->r1c2 + matrix2->r1c2;
+ sum->r1c3 = matrix1->r1c3 + matrix2->r1c3;
+
+ sum->r2c1 = matrix1->r2c1 + matrix2->r2c1;
+ sum->r2c2 = matrix1->r2c2 + matrix2->r2c2;
+ sum->r2c3 = matrix1->r2c3 + matrix2->r2c3;
+}
+
+// ================ Subtraction ================= //
+
+static inline void bg_fp32_matrix3x2_subtract(const BgFP32Matrix3x2* minuend, const BgFP32Matrix3x2* subtrahend, BgFP32Matrix3x2* difference)
+{
+ difference->r1c1 = minuend->r1c1 - subtrahend->r1c1;
+ difference->r1c2 = minuend->r1c2 - subtrahend->r1c2;
+ difference->r1c3 = minuend->r1c3 - subtrahend->r1c3;
+
+ difference->r2c1 = minuend->r2c1 - subtrahend->r2c1;
+ difference->r2c2 = minuend->r2c2 - subtrahend->r2c2;
+ difference->r2c3 = minuend->r2c3 - subtrahend->r2c3;
+}
+
+static inline void bg_fp64_matrix3x2_subtract(const BgFP64Matrix3x2* minuend, const BgFP64Matrix3x2* subtrahend, BgFP64Matrix3x2* difference)
+{
+ difference->r1c1 = minuend->r1c1 - subtrahend->r1c1;
+ difference->r1c2 = minuend->r1c2 - subtrahend->r1c2;
+ difference->r1c3 = minuend->r1c3 - subtrahend->r1c3;
+
+ difference->r2c1 = minuend->r2c1 - subtrahend->r2c1;
+ difference->r2c2 = minuend->r2c2 - subtrahend->r2c2;
+ difference->r2c3 = minuend->r2c3 - subtrahend->r2c3;
+}
+
+// =============== Multiplication =============== //
+
+static inline void bg_fp32_matrix3x2_multiply(const BgFP32Matrix3x2* multiplicand, const float multiplier, BgFP32Matrix3x2* product)
+{
+ product->r1c1 = multiplicand->r1c1 * multiplier;
+ product->r1c2 = multiplicand->r1c2 * multiplier;
+ product->r1c3 = multiplicand->r1c3 * multiplier;
+
+ product->r2c1 = multiplicand->r2c1 * multiplier;
+ product->r2c2 = multiplicand->r2c2 * multiplier;
+ product->r2c3 = multiplicand->r2c3 * multiplier;
+}
+
+static inline void bg_fp64_matrix3x2_multiply(const BgFP64Matrix3x2* multiplicand, const double multiplier, BgFP64Matrix3x2* product)
+{
+ product->r1c1 = multiplicand->r1c1 * multiplier;
+ product->r1c2 = multiplicand->r1c2 * multiplier;
+ product->r1c3 = multiplicand->r1c3 * multiplier;
+
+ product->r2c1 = multiplicand->r2c1 * multiplier;
+ product->r2c2 = multiplicand->r2c2 * multiplier;
+ product->r2c3 = multiplicand->r2c3 * multiplier;
+}
+
+// ================== Division ================== //
+
+static inline void bg_fp32_matrix3x2_divide(const BgFP32Matrix3x2* dividend, const float divisor, BgFP32Matrix3x2* quotient)
+{
+ quotient->r1c1 = dividend->r1c1 / divisor;
+ quotient->r1c2 = dividend->r1c2 / divisor;
+ quotient->r1c3 = dividend->r1c3 / divisor;
+
+ quotient->r2c1 = dividend->r2c1 / divisor;
+ quotient->r2c2 = dividend->r2c2 / divisor;
+ quotient->r2c3 = dividend->r2c3 / divisor;
+}
+
+static inline void bg_fp64_matrix3x2_divide(const BgFP64Matrix3x2* dividend, const double divisor, BgFP64Matrix3x2* quotient)
+{
+ quotient->r1c1 = dividend->r1c1 / divisor;
+ quotient->r1c2 = dividend->r1c2 / divisor;
+ quotient->r1c3 = dividend->r1c3 / divisor;
+
+ quotient->r2c1 = dividend->r2c1 / divisor;
+ quotient->r2c2 = dividend->r2c2 / divisor;
+ quotient->r2c3 = dividend->r2c3 / divisor;
+}
+
+// ============ Left Vector Product ============= //
+
+static inline void bg_fp32_matrix3x2_left_product(const BgFP32Vector2* vector, const BgFP32Matrix3x2* matrix, BgFP32Vector3* result)
+{
+ result->x1 = vector->x1 * matrix->r1c1 + vector->x2 * matrix->r2c1;
+ result->x2 = vector->x1 * matrix->r1c2 + vector->x2 * matrix->r2c2;
+ result->x3 = vector->x1 * matrix->r1c3 + vector->x2 * matrix->r2c3;
+}
+
+static inline void bg_fp64_matrix3x2_left_product(const BgFP64Vector2* vector, const BgFP64Matrix3x2* matrix, BgFP64Vector3* result)
+{
+ result->x1 = vector->x1 * matrix->r1c1 + vector->x2 * matrix->r2c1;
+ result->x2 = vector->x1 * matrix->r1c2 + vector->x2 * matrix->r2c2;
+ result->x3 = vector->x1 * matrix->r1c3 + vector->x2 * matrix->r2c3;
+}
+
+// ============ Right Vector Product ============ //
+
+static inline void bg_fp32_matrix3x2_right_product(const BgFP32Matrix3x2* matrix, const BgFP32Vector3* vector, BgFP32Vector2* result)
+{
+ result->x1 = matrix->r1c1 * vector->x1 + matrix->r1c2 * vector->x2 + matrix->r1c3 * vector->x3;
+ result->x2 = matrix->r2c1 * vector->x1 + matrix->r2c2 * vector->x2 + matrix->r2c3 * vector->x3;
+}
+
+static inline void bg_fp64_matrix3x2_right_product(const BgFP64Matrix3x2* matrix, const BgFP64Vector3* vector, BgFP64Vector2* result)
+{
+ result->x1 = matrix->r1c1 * vector->x1 + matrix->r1c2 * vector->x2 + matrix->r1c3 * vector->x3;
+ result->x2 = matrix->r2c1 * vector->x1 + matrix->r2c2 * vector->x2 + matrix->r2c3 * vector->x3;
+}
+
+#endif
diff --git a/basic-geometry/matrix3x3.c b/basic-geometry/matrix3x3.c
new file mode 100644
index 0000000..357b3ca
--- /dev/null
+++ b/basic-geometry/matrix3x3.c
@@ -0,0 +1,145 @@
+#include "matrix3x3.h"
+
+// ================= Inversion ================== //
+
+int bg_fp32_matrix3x3_invert(BgFP32Matrix3x3* matrix)
+{
+ const float determinant = bg_fp32_matrix3x3_get_determinant(matrix);
+
+ if (-BG_FP32_EPSYLON <= determinant && determinant <= BG_FP32_EPSYLON) {
+ return 0;
+ }
+
+ const float r1c1 = matrix->r2c2 * matrix->r3c3 - matrix->r2c3 * matrix->r3c2;
+ const float r1c2 = matrix->r1c3 * matrix->r3c2 - matrix->r1c2 * matrix->r3c3;
+ const float r1c3 = matrix->r1c2 * matrix->r2c3 - matrix->r1c3 * matrix->r2c2;
+
+ const float r2c1 = matrix->r2c3 * matrix->r3c1 - matrix->r2c1 * matrix->r3c3;
+ const float r2c2 = matrix->r1c1 * matrix->r3c3 - matrix->r1c3 * matrix->r3c1;
+ const float r2c3 = matrix->r1c3 * matrix->r2c1 - matrix->r1c1 * matrix->r2c3;
+
+ const float r3c1 = matrix->r2c1 * matrix->r3c2 - matrix->r2c2 * matrix->r3c1;
+ const float r3c2 = matrix->r1c2 * matrix->r3c1 - matrix->r1c1 * matrix->r3c2;
+ const float r3c3 = matrix->r1c1 * matrix->r2c2 - matrix->r1c2 * matrix->r2c1;
+
+ matrix->r1c1 = r1c1 / determinant;
+ matrix->r1c2 = r1c2 / determinant;
+ matrix->r1c3 = r1c3 / determinant;
+
+ matrix->r2c1 = r2c1 / determinant;
+ matrix->r2c2 = r2c2 / determinant;
+ matrix->r2c3 = r2c3 / determinant;
+
+ matrix->r3c1 = r3c1 / determinant;
+ matrix->r3c2 = r3c2 / determinant;
+ matrix->r3c3 = r3c3 / determinant;
+
+ return 1;
+}
+
+int bg_fp64_matrix3x3_invert(BgFP64Matrix3x3* matrix)
+{
+ const double determinant = bg_fp64_matrix3x3_get_determinant(matrix);
+
+ if (-BG_FP64_EPSYLON <= determinant && determinant <= BG_FP64_EPSYLON) {
+ return 0;
+ }
+
+ const double r1c1 = matrix->r2c2 * matrix->r3c3 - matrix->r2c3 * matrix->r3c2;
+ const double r1c2 = matrix->r1c3 * matrix->r3c2 - matrix->r1c2 * matrix->r3c3;
+ const double r1c3 = matrix->r1c2 * matrix->r2c3 - matrix->r1c3 * matrix->r2c2;
+
+ const double r2c1 = matrix->r2c3 * matrix->r3c1 - matrix->r2c1 * matrix->r3c3;
+ const double r2c2 = matrix->r1c1 * matrix->r3c3 - matrix->r1c3 * matrix->r3c1;
+ const double r2c3 = matrix->r1c3 * matrix->r2c1 - matrix->r1c1 * matrix->r2c3;
+
+ const double r3c1 = matrix->r2c1 * matrix->r3c2 - matrix->r2c2 * matrix->r3c1;
+ const double r3c2 = matrix->r1c2 * matrix->r3c1 - matrix->r1c1 * matrix->r3c2;
+ const double r3c3 = matrix->r1c1 * matrix->r2c2 - matrix->r1c2 * matrix->r2c1;
+
+ matrix->r1c1 = r1c1 / determinant;
+ matrix->r1c2 = r1c2 / determinant;
+ matrix->r1c3 = r1c3 / determinant;
+
+ matrix->r2c1 = r2c1 / determinant;
+ matrix->r2c2 = r2c2 / determinant;
+ matrix->r2c3 = r2c3 / determinant;
+
+ matrix->r3c1 = r3c1 / determinant;
+ matrix->r3c2 = r3c2 / determinant;
+ matrix->r3c3 = r3c3 / determinant;
+
+ return 1;
+}
+
+// ================ Make Inverted =============== //
+
+int bg_fp32_matrix3x3_set_inverted(const BgFP32Matrix3x3* matrix, BgFP32Matrix3x3* result)
+{
+ const float determinant = bg_fp32_matrix3x3_get_determinant(matrix);
+
+ if (-BG_FP32_EPSYLON <= determinant && determinant <= BG_FP32_EPSYLON) {
+ return 0;
+ }
+
+ const float r1c1 = matrix->r2c2 * matrix->r3c3 - matrix->r2c3 * matrix->r3c2;
+ const float r1c2 = matrix->r1c3 * matrix->r3c2 - matrix->r1c2 * matrix->r3c3;
+ const float r1c3 = matrix->r1c2 * matrix->r2c3 - matrix->r1c3 * matrix->r2c2;
+
+ const float r2c1 = matrix->r2c3 * matrix->r3c1 - matrix->r2c1 * matrix->r3c3;
+ const float r2c2 = matrix->r1c1 * matrix->r3c3 - matrix->r1c3 * matrix->r3c1;
+ const float r2c3 = matrix->r1c3 * matrix->r2c1 - matrix->r1c1 * matrix->r2c3;
+
+ const float r3c1 = matrix->r2c1 * matrix->r3c2 - matrix->r2c2 * matrix->r3c1;
+ const float r3c2 = matrix->r1c2 * matrix->r3c1 - matrix->r1c1 * matrix->r3c2;
+ const float r3c3 = matrix->r1c1 * matrix->r2c2 - matrix->r1c2 * matrix->r2c1;
+
+ result->r1c1 = r1c1 / determinant;
+ result->r1c2 = r1c2 / determinant;
+ result->r1c3 = r1c3 / determinant;
+
+ result->r2c1 = r2c1 / determinant;
+ result->r2c2 = r2c2 / determinant;
+ result->r2c3 = r2c3 / determinant;
+
+ result->r3c1 = r3c1 / determinant;
+ result->r3c2 = r3c2 / determinant;
+ result->r3c3 = r3c3 / determinant;
+
+ return 1;
+}
+
+int bg_fp64_matrix3x3_set_inverted(const BgFP64Matrix3x3* matrix, BgFP64Matrix3x3* result)
+{
+ const double determinant = bg_fp64_matrix3x3_get_determinant(matrix);
+
+ if (-BG_FP64_EPSYLON <= determinant && determinant <= BG_FP64_EPSYLON) {
+ return 0;
+ }
+
+ const double r1c1 = matrix->r2c2 * matrix->r3c3 - matrix->r2c3 * matrix->r3c2;
+ const double r1c2 = matrix->r1c3 * matrix->r3c2 - matrix->r1c2 * matrix->r3c3;
+ const double r1c3 = matrix->r1c2 * matrix->r2c3 - matrix->r1c3 * matrix->r2c2;
+
+ const double r2c1 = matrix->r2c3 * matrix->r3c1 - matrix->r2c1 * matrix->r3c3;
+ const double r2c2 = matrix->r1c1 * matrix->r3c3 - matrix->r1c3 * matrix->r3c1;
+ const double r2c3 = matrix->r1c3 * matrix->r2c1 - matrix->r1c1 * matrix->r2c3;
+
+ const double r3c1 = matrix->r2c1 * matrix->r3c2 - matrix->r2c2 * matrix->r3c1;
+ const double r3c2 = matrix->r1c2 * matrix->r3c1 - matrix->r1c1 * matrix->r3c2;
+ const double r3c3 = matrix->r1c1 * matrix->r2c2 - matrix->r1c2 * matrix->r2c1;
+
+ result->r1c1 = r1c1 / determinant;
+ result->r1c2 = r1c2 / determinant;
+ result->r1c3 = r1c3 / determinant;
+
+ result->r2c1 = r2c1 / determinant;
+ result->r2c2 = r2c2 / determinant;
+ result->r2c3 = r2c3 / determinant;
+
+ result->r3c1 = r3c1 / determinant;
+ result->r3c2 = r3c2 / determinant;
+ result->r3c3 = r3c3 / determinant;
+
+ return 1;
+}
diff --git a/basic-geometry/matrix3x3.h b/basic-geometry/matrix3x3.h
new file mode 100644
index 0000000..d8a2fab
--- /dev/null
+++ b/basic-geometry/matrix3x3.h
@@ -0,0 +1,585 @@
+#ifndef _GEOMETRY_MATRIX3X3_H_
+#define _GEOMETRY_MATRIX3X3_H_
+
+#include "vector3.h"
+#include "matrixes.h"
+
+// =================== Reset ==================== //
+
+static inline void bg_fp32_matrix3x3_reset(BgFP32Matrix3x3* matrix)
+{
+ matrix->r1c1 = 0.0f;
+ matrix->r1c2 = 0.0f;
+ matrix->r1c3 = 0.0f;
+
+ matrix->r2c1 = 0.0f;
+ matrix->r2c2 = 0.0f;
+ matrix->r2c3 = 0.0f;
+
+ matrix->r3c1 = 0.0f;
+ matrix->r3c2 = 0.0f;
+ matrix->r3c3 = 0.0f;
+}
+
+static inline void bg_fp64_matrix3x3_reset(BgFP64Matrix3x3* matrix)
+{
+ matrix->r1c1 = 0.0;
+ matrix->r1c2 = 0.0;
+ matrix->r1c3 = 0.0;
+
+ matrix->r2c1 = 0.0;
+ matrix->r2c2 = 0.0;
+ matrix->r2c3 = 0.0;
+
+ matrix->r3c1 = 0.0;
+ matrix->r3c2 = 0.0;
+ matrix->r3c3 = 0.0;
+}
+
+// ================== Identity ================== //
+
+static inline void bg_fp32_matrix3x3_set_to_identity(BgFP32Matrix3x3* matrix)
+{
+ matrix->r1c1 = 1.0f;
+ matrix->r1c2 = 0.0f;
+ matrix->r1c3 = 0.0f;
+
+ matrix->r2c1 = 0.0f;
+ matrix->r2c2 = 1.0f;
+ matrix->r2c3 = 0.0f;
+
+ matrix->r3c1 = 0.0f;
+ matrix->r3c2 = 0.0f;
+ matrix->r3c3 = 1.0f;
+}
+
+static inline void bg_fp64_matrix3x3_set_to_identity(BgFP64Matrix3x3* matrix)
+{
+ matrix->r1c1 = 1.0;
+ matrix->r1c2 = 0.0;
+ matrix->r1c3 = 0.0;
+
+ matrix->r2c1 = 0.0;
+ matrix->r2c2 = 1.0;
+ matrix->r2c3 = 0.0;
+
+ matrix->r3c1 = 0.0;
+ matrix->r3c2 = 0.0;
+ matrix->r3c3 = 1.0;
+}
+
+// ================ Make Diagonal =============== //
+
+static inline void bg_fp32_matrix3x3_set_to_diagonal(const float d1, const float d2, const float d3, BgFP32Matrix3x3* matrix)
+{
+ matrix->r1c1 = d1;
+ matrix->r1c2 = 0.0f;
+ matrix->r1c3 = 0.0f;
+
+ matrix->r2c1 = 0.0f;
+ matrix->r2c2 = d2;
+ matrix->r2c3 = 0.0f;
+
+ matrix->r3c1 = 0.0f;
+ matrix->r3c2 = 0.0f;
+ matrix->r3c3 = d2;
+}
+
+static inline void bg_fp64_matrix3x3_set_to_diagonal(const double d1, const double d2, const double d3, BgFP64Matrix3x3* matrix)
+{
+ matrix->r1c1 = d1;
+ matrix->r1c2 = 0.0;
+ matrix->r1c3 = 0.0;
+
+ matrix->r2c1 = 0.0;
+ matrix->r2c2 = d2;
+ matrix->r2c3 = 0.0;
+
+ matrix->r3c1 = 0.0;
+ matrix->r3c2 = 0.0;
+ matrix->r3c3 = d2;
+}
+
+// ==================== Copy ==================== //
+
+static inline void bg_fp32_matrix3x3_copy(const BgFP32Matrix3x3* from, BgFP32Matrix3x3* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r1c2;
+ to->r1c3 = from->r1c3;
+
+ to->r2c1 = from->r2c1;
+ to->r2c2 = from->r2c2;
+ to->r2c3 = from->r2c3;
+
+ to->r3c1 = from->r3c1;
+ to->r3c2 = from->r3c2;
+ to->r3c3 = from->r3c3;
+}
+
+static inline void bg_fp64_matrix3x3_copy(const BgFP64Matrix3x3* from, BgFP64Matrix3x3* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r1c2;
+ to->r1c3 = from->r1c3;
+
+ to->r2c1 = from->r2c1;
+ to->r2c2 = from->r2c2;
+ to->r2c3 = from->r2c3;
+
+ to->r3c1 = from->r3c1;
+ to->r3c2 = from->r3c2;
+ to->r3c3 = from->r3c3;
+}
+
+// ============= Set from twin type ============= //
+
+static inline void bg_fp32_matrix3x3_set_from_fp64(const BgFP64Matrix3x3* from, BgFP32Matrix3x3* to)
+{
+ to->r1c1 = (float) from->r1c1;
+ to->r1c2 = (float) from->r1c2;
+ to->r1c3 = (float) from->r1c3;
+
+ to->r2c1 = (float) from->r2c1;
+ to->r2c2 = (float) from->r2c2;
+ to->r2c3 = (float) from->r2c3;
+
+ to->r3c1 = (float) from->r3c1;
+ to->r3c2 = (float) from->r3c2;
+ to->r3c3 = (float) from->r3c3;
+}
+
+static inline void bg_fp64_matrix3x3_set_from_fp32(const BgFP32Matrix3x3* from, BgFP64Matrix3x3* to)
+{
+ to->r1c1 = from->r1c1;
+ to->r1c2 = from->r1c2;
+ to->r1c3 = from->r1c3;
+
+ to->r2c1 = from->r2c1;
+ to->r2c2 = from->r2c2;
+ to->r2c3 = from->r2c3;
+
+ to->r3c1 = from->r3c1;
+ to->r3c2 = from->r3c2;
+ to->r3c3 = from->r3c3;
+}
+
+// ================ Determinant ================= //
+
+static inline float bg_fp32_matrix3x3_get_determinant(const BgFP32Matrix3x3* matrix)
+{
+ return matrix->r1c1 * (matrix->r2c2 * matrix->r3c3 - matrix->r2c3 * matrix->r3c2)
+ + matrix->r1c2 * (matrix->r2c3 * matrix->r3c1 - matrix->r2c1 * matrix->r3c3)
+ + matrix->r1c3 * (matrix->r2c1 * matrix->r3c2 - matrix->r2c2 * matrix->r3c1);
+}
+
+static inline double bg_fp64_matrix3x3_get_determinant(const BgFP64Matrix3x3* matrix)
+{
+ return matrix->r1c1 * (matrix->r2c2 * matrix->r3c3 - matrix->r2c3 * matrix->r3c2)
+ + matrix->r1c2 * (matrix->r2c3 * matrix->r3c1 - matrix->r2c1 * matrix->r3c3)
+ + matrix->r1c3 * (matrix->r2c1 * matrix->r3c2 - matrix->r2c2 * matrix->r3c1);
+}
+
+// ================== Singular ================== //
+
+static inline int bg_fp32_matrix3x3_is_singular(const BgFP32Matrix3x3* matrix)
+{
+ const float determinant = bg_fp32_matrix3x3_get_determinant(matrix);
+
+ return -BG_FP32_EPSYLON <= determinant && determinant <= BG_FP32_EPSYLON;
+}
+
+static inline int bg_fp64_matrix3x3_is_singular(const BgFP64Matrix3x3* matrix)
+{
+ const double determinant = bg_fp64_matrix3x3_get_determinant(matrix);
+
+ return -BG_FP64_EPSYLON <= determinant && determinant <= BG_FP64_EPSYLON;
+}
+
+// ================= Inversion ================== //
+
+int bg_fp32_matrix3x3_invert(BgFP32Matrix3x3* matrix);
+
+int bg_fp64_matrix3x3_invert(BgFP64Matrix3x3* matrix);
+
+// =============== Transposition ================ //
+
+static inline void bg_fp32_matrix3x3_transpose(BgFP32Matrix3x3* matrix)
+{
+ float tmp = matrix->r1c2;
+ matrix->r1c2 = matrix->r2c1;
+ matrix->r2c1 = tmp;
+
+ tmp = matrix->r1c3;
+ matrix->r1c3 = matrix->r3c1;
+ matrix->r3c1 = tmp;
+
+ tmp = matrix->r2c3;
+ matrix->r2c3 = matrix->r3c2;
+ matrix->r3c2 = tmp;
+}
+
+static inline void bg_fp64_matrix3x3_transpose(BgFP64Matrix3x3* matrix)
+{
+ double tmp = matrix->r1c2;
+ matrix->r1c2 = matrix->r2c1;
+ matrix->r2c1 = tmp;
+
+ tmp = matrix->r1c3;
+ matrix->r1c3 = matrix->r3c1;
+ matrix->r3c1 = tmp;
+
+ tmp = matrix->r2c3;
+ matrix->r2c3 = matrix->r3c2;
+ matrix->r3c2 = tmp;
+}
+
+// ================ Make Inverted =============== //
+
+int bg_fp32_matrix3x3_set_inverted(const BgFP32Matrix3x3* matrix, BgFP32Matrix3x3* result);
+
+int bg_fp64_matrix3x3_set_inverted(const BgFP64Matrix3x3* matrix, BgFP64Matrix3x3* result);
+
+// =============== Make Transposed ============== //
+
+static inline void bg_fp32_matrix3x3_set_transposed(const BgFP32Matrix3x3* matrix, BgFP32Matrix3x3* result)
+{
+ if (matrix == result) {
+ bg_fp32_matrix3x3_transpose(result);
+ return;
+ }
+
+ result->r1c1 = matrix->r1c1;
+ result->r1c2 = matrix->r2c1;
+ result->r1c3 = matrix->r3c1;
+
+ result->r2c1 = matrix->r1c2;
+ result->r2c2 = matrix->r2c2;
+ result->r2c3 = matrix->r3c2;
+
+ result->r3c1 = matrix->r1c3;
+ result->r3c2 = matrix->r2c3;
+ result->r3c3 = matrix->r3c3;
+}
+
+static inline void bg_fp64_matrix3x3_set_transposed(const BgFP64Matrix3x3* matrix, BgFP64Matrix3x3* result)
+{
+ if (matrix == result) {
+ bg_fp64_matrix3x3_transpose(result);
+ return;
+ }
+
+ result->r1c1 = matrix->r1c1;
+ result->r1c2 = matrix->r2c1;
+ result->r1c3 = matrix->r3c1;
+
+ result->r2c1 = matrix->r1c2;
+ result->r2c2 = matrix->r2c2;
+ result->r2c3 = matrix->r3c2;
+
+ result->r3c1 = matrix->r1c3;
+ result->r3c2 = matrix->r2c3;
+ result->r3c3 = matrix->r3c3;
+}
+
+// ================= Set Row 1 ================== //
+
+static inline void bg_fp32_matrix3x3_set_row1(const float c1, const float c2, const float c3, BgFP32Matrix3x3* matrix)
+{
+ matrix->r1c1 = c1;
+ matrix->r1c2 = c2;
+ matrix->r1c3 = c3;
+}
+
+static inline void bg_fp64_matrix3x3_set_row1(const double c1, const double c2, const double c3, BgFP64Matrix3x3* matrix)
+{
+ matrix->r1c1 = c1;
+ matrix->r1c2 = c2;
+ matrix->r1c3 = c3;
+}
+
+// ================= Set Row 2 ================== //
+
+static inline void bg_fp32_matrix3x3_set_row2(const float c1, const float c2, const float c3, BgFP32Matrix3x3* matrix)
+{
+ matrix->r2c1 = c1;
+ matrix->r2c2 = c2;
+ matrix->r2c3 = c3;
+}
+
+static inline void bg_fp64_matrix3x3_set_row2(const double c1, const double c2, const double c3, BgFP64Matrix3x3* matrix)
+{
+ matrix->r2c1 = c1;
+ matrix->r2c2 = c2;
+ matrix->r2c3 = c3;
+}
+
+// ================= Set Row 3 ================== //
+
+static inline void bg_fp32_matrix3x3_set_row3(const float c1, const float c2, const float c3, BgFP32Matrix3x3* matrix)
+{
+ matrix->r3c1 = c1;
+ matrix->r3c2 = c2;
+ matrix->r3c3 = c3;
+}
+
+static inline void bg_fp64_matrix3x3_set_row3(const double c1, const double c2, const double c3, BgFP64Matrix3x3* matrix)
+{
+ matrix->r3c1 = c1;
+ matrix->r3c2 = c2;
+ matrix->r3c3 = c3;
+}
+
+// ================ Set Column 1 ================ //
+
+static inline void bg_fp32_matrix3x3_set_column1(const float r1, const float r2, const float r3, BgFP32Matrix3x3* matrix)
+{
+ matrix->r1c1 = r1;
+ matrix->r2c1 = r2;
+ matrix->r3c1 = r3;
+}
+
+static inline void bg_fp64_matrix3x3_set_column1(const double r1, const double r2, const double r3, BgFP64Matrix3x3* matrix)
+{
+ matrix->r1c1 = r1;
+ matrix->r2c1 = r2;
+ matrix->r3c1 = r3;
+}
+
+// ================ Set Column 2 ================ //
+
+static inline void bg_fp32_matrix3x3_set_column2(const float r1, const float r2, const float r3, BgFP32Matrix3x3* matrix)
+{
+ matrix->r1c2 = r1;
+ matrix->r2c2 = r2;
+ matrix->r3c2 = r3;
+}
+
+static inline void bg_fp64_matrix3x3_set_column2(const double r1, const double r2, const double r3, BgFP64Matrix3x3* matrix)
+{
+ matrix->r1c2 = r1;
+ matrix->r2c2 = r2;
+ matrix->r3c2 = r3;
+}
+
+// ================ Set Column 3 ================ //
+
+static inline void bg_fp32_matrix3x3_set_column3(const float r1, const float r2, const float r3, BgFP32Matrix3x3* matrix)
+{
+ matrix->r1c3 = r1;
+ matrix->r2c3 = r2;
+ matrix->r3c3 = r3;
+}
+
+static inline void bg_fp64_matrix3x3_set_column3(const double r1, const double r2, const double r3, BgFP64Matrix3x3* matrix)
+{
+ matrix->r1c3 = r1;
+ matrix->r2c3 = r2;
+ matrix->r3c3 = r3;
+}
+
+// ================ Append scaled =============== //
+
+static inline void bg_fp32_matrix3x3_append_scaled(BgFP32Matrix3x3* basic_vector, const BgFP32Matrix3x3* scalable_vector, const float scale)
+{
+ basic_vector->r1c1 += scalable_vector->r1c1 * scale;
+ basic_vector->r1c2 += scalable_vector->r1c2 * scale;
+ basic_vector->r1c3 += scalable_vector->r1c3 * scale;
+
+ basic_vector->r2c1 += scalable_vector->r2c1 * scale;
+ basic_vector->r2c2 += scalable_vector->r2c2 * scale;
+ basic_vector->r2c3 += scalable_vector->r2c3 * scale;
+
+ basic_vector->r3c1 += scalable_vector->r3c1 * scale;
+ basic_vector->r3c2 += scalable_vector->r3c2 * scale;
+ basic_vector->r3c3 += scalable_vector->r3c3 * scale;
+}
+
+static inline void bg_fp64_matrix3x3_append_scaled(BgFP64Matrix3x3* basic_vector, const BgFP64Matrix3x3* scalable_vector, const double scale)
+{
+ basic_vector->r1c1 += scalable_vector->r1c1 * scale;
+ basic_vector->r1c2 += scalable_vector->r1c2 * scale;
+ basic_vector->r1c3 += scalable_vector->r1c3 * scale;
+
+ basic_vector->r2c1 += scalable_vector->r2c1 * scale;
+ basic_vector->r2c2 += scalable_vector->r2c2 * scale;
+ basic_vector->r2c3 += scalable_vector->r2c3 * scale;
+
+ basic_vector->r3c1 += scalable_vector->r3c1 * scale;
+ basic_vector->r3c2 += scalable_vector->r3c2 * scale;
+ basic_vector->r3c3 += scalable_vector->r3c3 * scale;
+}
+
+// ================== Addition ================== //
+
+static inline void bg_fp32_matrix3x3_add(const BgFP32Matrix3x3* matrix1, const BgFP32Matrix3x3* matrix2, BgFP32Matrix3x3* sum)
+{
+ sum->r1c1 = matrix1->r1c1 + matrix2->r1c1;
+ sum->r1c2 = matrix1->r1c2 + matrix2->r1c2;
+ sum->r1c3 = matrix1->r1c3 + matrix2->r1c3;
+
+ sum->r2c1 = matrix1->r2c1 + matrix2->r2c1;
+ sum->r2c2 = matrix1->r2c2 + matrix2->r2c2;
+ sum->r2c3 = matrix1->r2c3 + matrix2->r2c3;
+
+ sum->r3c1 = matrix1->r3c1 + matrix2->r3c1;
+ sum->r3c2 = matrix1->r3c2 + matrix2->r3c2;
+ sum->r3c3 = matrix1->r3c3 + matrix2->r3c3;
+}
+
+static inline void bg_fp64_matrix3x3_add(const BgFP64Matrix3x3* matrix1, const BgFP64Matrix3x3* matrix2, BgFP64Matrix3x3* sum)
+{
+ sum->r1c1 = matrix1->r1c1 + matrix2->r1c1;
+ sum->r1c2 = matrix1->r1c2 + matrix2->r1c2;
+ sum->r1c3 = matrix1->r1c3 + matrix2->r1c3;
+
+ sum->r2c1 = matrix1->r2c1 + matrix2->r2c1;
+ sum->r2c2 = matrix1->r2c2 + matrix2->r2c2;
+ sum->r2c3 = matrix1->r2c3 + matrix2->r2c3;
+
+ sum->r3c1 = matrix1->r3c1 + matrix2->r3c1;
+ sum->r3c2 = matrix1->r3c2 + matrix2->r3c2;
+ sum->r3c3 = matrix1->r3c3 + matrix2->r3c3;
+}
+
+// ================ Subtraction ================= //
+
+static inline void bg_fp32_matrix3x3_subtract(const BgFP32Matrix3x3* minuend, const BgFP32Matrix3x3* subtrahend, BgFP32Matrix3x3* difference)
+{
+ difference->r1c1 = minuend->r1c1 - subtrahend->r1c1;
+ difference->r1c2 = minuend->r1c2 - subtrahend->r1c2;
+ difference->r1c3 = minuend->r1c3 - subtrahend->r1c3;
+
+ difference->r2c1 = minuend->r2c1 - subtrahend->r2c1;
+ difference->r2c2 = minuend->r2c2 - subtrahend->r2c2;
+ difference->r2c3 = minuend->r2c3 - subtrahend->r2c3;
+
+ difference->r3c1 = minuend->r3c1 - subtrahend->r3c1;
+ difference->r3c2 = minuend->r3c2 - subtrahend->r3c2;
+ difference->r3c3 = minuend->r3c3 - subtrahend->r3c3;
+}
+
+static inline void bg_fp64_matrix3x3_subtract(const BgFP64Matrix3x3* minuend, const BgFP64Matrix3x3* subtrahend, BgFP64Matrix3x3* difference)
+{
+ difference->r1c1 = minuend->r1c1 - subtrahend->r1c1;
+ difference->r1c2 = minuend->r1c2 - subtrahend->r1c2;
+ difference->r1c3 = minuend->r1c3 - subtrahend->r1c3;
+
+ difference->r2c1 = minuend->r2c1 - subtrahend->r2c1;
+ difference->r2c2 = minuend->r2c2 - subtrahend->r2c2;
+ difference->r2c3 = minuend->r2c3 - subtrahend->r2c3;
+
+ difference->r3c1 = minuend->r3c1 - subtrahend->r3c1;
+ difference->r3c2 = minuend->r3c2 - subtrahend->r3c2;
+ difference->r3c3 = minuend->r3c3 - subtrahend->r3c3;
+}
+
+// =============== Multiplication =============== //
+
+static inline void bg_fp32_matrix3x3_multiply(const BgFP32Matrix3x3* multiplicand, const float multiplier, BgFP32Matrix3x3* product)
+{
+ product->r1c1 = multiplicand->r1c1 * multiplier;
+ product->r1c2 = multiplicand->r1c2 * multiplier;
+ product->r1c3 = multiplicand->r1c3 * multiplier;
+
+ product->r2c1 = multiplicand->r2c1 * multiplier;
+ product->r2c2 = multiplicand->r2c2 * multiplier;
+ product->r2c3 = multiplicand->r2c3 * multiplier;
+
+ product->r3c1 = multiplicand->r3c1 * multiplier;
+ product->r3c2 = multiplicand->r3c2 * multiplier;
+ product->r3c3 = multiplicand->r3c3 * multiplier;
+}
+
+static inline void bg_fp64_matrix3x3_multiply(const BgFP64Matrix3x3* multiplicand, const double multiplier, BgFP64Matrix3x3* product)
+{
+ product->r1c1 = multiplicand->r1c1 * multiplier;
+ product->r1c2 = multiplicand->r1c2 * multiplier;
+ product->r1c3 = multiplicand->r1c3 * multiplier;
+
+ product->r2c1 = multiplicand->r2c1 * multiplier;
+ product->r2c2 = multiplicand->r2c2 * multiplier;
+ product->r2c3 = multiplicand->r2c3 * multiplier;
+
+ product->r3c1 = multiplicand->r3c1 * multiplier;
+ product->r3c2 = multiplicand->r3c2 * multiplier;
+ product->r3c3 = multiplicand->r3c3 * multiplier;
+}
+
+// ================== Division ================== //
+
+static inline void bg_fp32_matrix3x3_divide(const BgFP32Matrix3x3* dividend, const float divisor, BgFP32Matrix3x3* quotient)
+{
+ quotient->r1c1 = dividend->r1c1 / divisor;
+ quotient->r1c2 = dividend->r1c2 / divisor;
+ quotient->r1c3 = dividend->r1c3 / divisor;
+
+ quotient->r2c1 = dividend->r2c1 / divisor;
+ quotient->r2c2 = dividend->r2c2 / divisor;
+ quotient->r2c3 = dividend->r2c3 / divisor;
+
+ quotient->r3c1 = dividend->r3c1 / divisor;
+ quotient->r3c2 = dividend->r3c2 / divisor;
+ quotient->r3c3 = dividend->r3c3 / divisor;
+}
+
+static inline void bg_fp64_matrix3x3_divide(const BgFP64Matrix3x3* dividend, const double divisor, BgFP64Matrix3x3* quotient)
+{
+ quotient->r1c1 = dividend->r1c1 / divisor;
+ quotient->r1c2 = dividend->r1c2 / divisor;
+ quotient->r1c3 = dividend->r1c3 / divisor;
+
+ quotient->r2c1 = dividend->r2c1 / divisor;
+ quotient->r2c2 = dividend->r2c2 / divisor;
+ quotient->r2c3 = dividend->r2c3 / divisor;
+
+ quotient->r3c1 = dividend->r3c1 / divisor;
+ quotient->r3c2 = dividend->r3c2 / divisor;
+ quotient->r3c3 = dividend->r3c3 / divisor;
+}
+
+// ============ Left Vector Product ============= //
+
+static inline void bg_fp32_matrix3x3_left_product(const BgFP32Vector3* vector, const BgFP32Matrix3x3* matrix, BgFP32Vector3* result)
+{
+ bg_fp32_vector3_set_values(
+ vector->x1 * matrix->r1c1 + vector->x2 * matrix->r2c1 + vector->x3 * matrix->r3c1,
+ vector->x1 * matrix->r1c2 + vector->x2 * matrix->r2c2 + vector->x3 * matrix->r3c2,
+ vector->x1 * matrix->r1c3 + vector->x2 * matrix->r2c3 + vector->x3 * matrix->r3c3,
+ result
+ );
+}
+
+static inline void bg_fp64_matrix3x3_left_product(const BgFP64Vector3* vector, const BgFP64Matrix3x3* matrix, BgFP64Vector3* result)
+{
+ bg_fp64_vector3_set_values(
+ vector->x1 * matrix->r1c1 + vector->x2 * matrix->r2c1 + vector->x3 * matrix->r3c1,
+ vector->x1 * matrix->r1c2 + vector->x2 * matrix->r2c2 + vector->x3 * matrix->r3c2,
+ vector->x1 * matrix->r1c3 + vector->x2 * matrix->r2c3 + vector->x3 * matrix->r3c3,
+ result
+ );
+}
+
+// ============ Right Vector Product ============ //
+
+static inline void bg_fp32_matrix3x3_right_product(const BgFP32Matrix3x3* matrix, const BgFP32Vector3* vector, BgFP32Vector3* result)
+{
+ bg_fp32_vector3_set_values(
+ matrix->r1c1 * vector->x1 + matrix->r1c2 * vector->x2 + matrix->r1c3 * vector->x3,
+ matrix->r2c1 * vector->x1 + matrix->r2c2 * vector->x2 + matrix->r2c3 * vector->x3,
+ matrix->r3c1 * vector->x1 + matrix->r3c2 * vector->x2 + matrix->r3c3 * vector->x3,
+ result
+ );
+}
+
+static inline void bg_fp64_matrix3x3_right_product(const BgFP64Matrix3x3* matrix, const BgFP64Vector3* vector, BgFP64Vector3* result)
+{
+ bg_fp64_vector3_set_values(
+ matrix->r1c1 * vector->x1 + matrix->r1c2 * vector->x2 + matrix->r1c3 * vector->x3,
+ matrix->r2c1 * vector->x1 + matrix->r2c2 * vector->x2 + matrix->r2c3 * vector->x3,
+ matrix->r3c1 * vector->x1 + matrix->r3c2 * vector->x2 + matrix->r3c3 * vector->x3,
+ result
+ );
+}
+
+#endif
diff --git a/basic-geometry/matrixes.c b/basic-geometry/matrixes.c
new file mode 100644
index 0000000..4da4587
--- /dev/null
+++ b/basic-geometry/matrixes.c
@@ -0,0 +1,277 @@
+#include "matrixes.h"
+
+// ========== Matrix Product 2x2 at 3x2 ========= //
+
+void bg_fp32_matrix_product_2x2_at_3x2(const BgFP32Matrix2x2* matrix1, const BgFP32Matrix3x2* matrix2, BgFP32Matrix3x2* result)
+{
+ const float r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1;
+ const float r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2;
+ const float r1c3 = matrix1->r1c1 * matrix2->r1c3 + matrix1->r1c2 * matrix2->r2c3;
+
+ const float r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1;
+ const float r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2;
+ const float r2c3 = matrix1->r2c1 * matrix2->r1c3 + matrix1->r2c2 * matrix2->r2c3;
+
+ result->r1c1 = r1c1;
+ result->r1c2 = r1c2;
+ result->r1c3 = r1c3;
+
+ result->r2c1 = r2c1;
+ result->r2c2 = r2c2;
+ result->r2c3 = r2c3;
+}
+
+void bg_fp64_matrix_product_2x2_at_3x2(const BgFP64Matrix2x2* matrix1, const BgFP64Matrix3x2* matrix2, BgFP64Matrix3x2* result)
+{
+ const double r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1;
+ const double r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2;
+ const double r1c3 = matrix1->r1c1 * matrix2->r1c3 + matrix1->r1c2 * matrix2->r2c3;
+
+ const double r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1;
+ const double r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2;
+ const double r2c3 = matrix1->r2c1 * matrix2->r1c3 + matrix1->r2c2 * matrix2->r2c3;
+
+ result->r1c1 = r1c1;
+ result->r1c2 = r1c2;
+ result->r1c3 = r1c3;
+
+ result->r2c1 = r2c1;
+ result->r2c2 = r2c2;
+ result->r2c3 = r2c3;
+}
+
+// ========== Matrix Product 2x3 at 2x2 ========= //
+
+void bg_fp32_matrix_product_2x3_at_2x2(const BgFP32Matrix2x3* matrix1, const BgFP32Matrix2x2* matrix2, BgFP32Matrix2x3* result)
+{
+ const float r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1;
+ const float r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2;
+
+ const float r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1;
+ const float r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2;
+
+ const float r3c1 = matrix1->r3c1 * matrix2->r1c1 + matrix1->r3c2 * matrix2->r2c1;
+ const float r3c2 = matrix1->r3c1 * matrix2->r1c2 + matrix1->r3c2 * matrix2->r2c2;
+
+ result->r1c1 = r1c1;
+ result->r1c2 = r1c2;
+
+ result->r2c1 = r2c1;
+ result->r2c2 = r2c2;
+
+ result->r3c1 = r3c1;
+ result->r3c2 = r3c2;
+}
+
+void bg_fp64_matrix_product_2x3_at_2x2(const BgFP64Matrix2x3* matrix1, const BgFP64Matrix2x2* matrix2, BgFP64Matrix2x3* result)
+{
+ const double r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1;
+ const double r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2;
+
+ const double r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1;
+ const double r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2;
+
+ const double r3c1 = matrix1->r3c1 * matrix2->r1c1 + matrix1->r3c2 * matrix2->r2c1;
+ const double r3c2 = matrix1->r3c1 * matrix2->r1c2 + matrix1->r3c2 * matrix2->r2c2;
+
+ result->r1c1 = r1c1;
+ result->r1c2 = r1c2;
+
+ result->r2c1 = r2c1;
+ result->r2c2 = r2c2;
+
+ result->r3c1 = r3c1;
+ result->r3c2 = r3c2;
+}
+
+// ========== Matrix Product 2x3 at 3x2 ========= //
+
+void bg_fp32_matrix_product_2x3_at_3x2(const BgFP32Matrix2x3* matrix1, const BgFP32Matrix3x2* matrix2, BgFP32Matrix3x3* result)
+{
+ result->r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1;
+ result->r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2;
+ result->r1c3 = matrix1->r1c1 * matrix2->r1c3 + matrix1->r1c2 * matrix2->r2c3;
+
+ result->r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1;
+ result->r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2;
+ result->r2c3 = matrix1->r2c1 * matrix2->r1c3 + matrix1->r2c2 * matrix2->r2c3;
+
+ result->r3c1 = matrix1->r3c1 * matrix2->r1c1 + matrix1->r3c2 * matrix2->r2c1;
+ result->r3c2 = matrix1->r3c1 * matrix2->r1c2 + matrix1->r3c2 * matrix2->r2c2;
+ result->r3c3 = matrix1->r3c1 * matrix2->r1c3 + matrix1->r3c2 * matrix2->r2c3;
+}
+
+void bg_fp64_matrix_product_2x3_at_3x2(const BgFP64Matrix2x3* matrix1, const BgFP64Matrix3x2* matrix2, BgFP64Matrix3x3* result)
+{
+ result->r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1;
+ result->r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2;
+ result->r1c3 = matrix1->r1c1 * matrix2->r1c3 + matrix1->r1c2 * matrix2->r2c3;
+
+ result->r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1;
+ result->r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2;
+ result->r2c3 = matrix1->r2c1 * matrix2->r1c3 + matrix1->r2c2 * matrix2->r2c3;
+
+ result->r3c1 = matrix1->r3c1 * matrix2->r1c1 + matrix1->r3c2 * matrix2->r2c1;
+ result->r3c2 = matrix1->r3c1 * matrix2->r1c2 + matrix1->r3c2 * matrix2->r2c2;
+ result->r3c3 = matrix1->r3c1 * matrix2->r1c3 + matrix1->r3c2 * matrix2->r2c3;
+}
+
+// ========== Matrix Product 3x2 at 2x3 ========= //
+
+void bg_fp32_matrix_product_3x2_at_2x3(const BgFP32Matrix3x2* matrix1, const BgFP32Matrix2x3* matrix2, BgFP32Matrix2x2* result)
+{
+ result->r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1 + matrix1->r1c3 * matrix2->r3c1;
+ result->r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2 + matrix1->r1c3 * matrix2->r3c2;
+
+ result->r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1 + matrix1->r2c3 * matrix2->r3c1;
+ result->r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2 + matrix1->r2c3 * matrix2->r3c2;
+}
+
+void bg_fp64_matrix_product_3x2_at_2x3(const BgFP64Matrix3x2* matrix1, const BgFP64Matrix2x3* matrix2, BgFP64Matrix2x2* result)
+{
+ result->r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1 + matrix1->r1c3 * matrix2->r3c1;
+ result->r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2 + matrix1->r1c3 * matrix2->r3c2;
+
+ result->r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1 + matrix1->r2c3 * matrix2->r3c1;
+ result->r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2 + matrix1->r2c3 * matrix2->r3c2;
+}
+
+// ========== Matrix Product 3x2 at 3x3 ========= //
+
+void bg_fp32_matrix_product_3x2_at_3x3(const BgFP32Matrix3x2* matrix1, const BgFP32Matrix3x3* matrix2, BgFP32Matrix3x2* result)
+{
+ const float r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1 + matrix1->r1c3 * matrix2->r3c1;
+ const float r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2 + matrix1->r1c3 * matrix2->r3c2;
+ const float r1c3 = matrix1->r1c1 * matrix2->r1c3 + matrix1->r1c2 * matrix2->r2c3 + matrix1->r1c3 * matrix2->r3c3;
+
+ const float r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1 + matrix1->r2c3 * matrix2->r3c1;
+ const float r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2 + matrix1->r2c3 * matrix2->r3c2;
+ const float r2c3 = matrix1->r2c1 * matrix2->r1c3 + matrix1->r2c2 * matrix2->r2c3 + matrix1->r2c3 * matrix2->r3c3;
+
+ result->r1c1 = r1c1;
+ result->r1c2 = r1c2;
+ result->r1c3 = r1c3;
+
+ result->r2c1 = r2c1;
+ result->r2c2 = r2c2;
+ result->r2c3 = r2c3;
+}
+
+void bg_fp64_matrix_product_3x2_at_3x3(const BgFP64Matrix3x2* matrix1, const BgFP64Matrix3x3* matrix2, BgFP64Matrix3x2* result)
+{
+ const double r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1 + matrix1->r1c3 * matrix2->r3c1;
+ const double r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2 + matrix1->r1c3 * matrix2->r3c2;
+ const double r1c3 = matrix1->r1c1 * matrix2->r1c3 + matrix1->r1c2 * matrix2->r2c3 + matrix1->r1c3 * matrix2->r3c3;
+
+ const double r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1 + matrix1->r2c3 * matrix2->r3c1;
+ const double r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2 + matrix1->r2c3 * matrix2->r3c2;
+ const double r2c3 = matrix1->r2c1 * matrix2->r1c3 + matrix1->r2c2 * matrix2->r2c3 + matrix1->r2c3 * matrix2->r3c3;
+
+ result->r1c1 = r1c1;
+ result->r1c2 = r1c2;
+ result->r1c3 = r1c3;
+
+ result->r2c1 = r2c1;
+ result->r2c2 = r2c2;
+ result->r2c3 = r2c3;
+}
+
+// ========== Matrix Product 3x3 at 2x3 ========= //
+
+void bg_fp32_matrix_product_3x3_at_2x3(const BgFP32Matrix3x3* matrix1, const BgFP32Matrix2x3* matrix2, BgFP32Matrix2x3* result)
+{
+ const float r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1 + matrix1->r1c3 * matrix2->r3c1;
+ const float r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2 + matrix1->r1c3 * matrix2->r3c2;
+
+ const float r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1 + matrix1->r2c3 * matrix2->r3c1;
+ const float r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2 + matrix1->r2c3 * matrix2->r3c2;
+
+ const float r3c1 = matrix1->r3c1 * matrix2->r1c1 + matrix1->r3c2 * matrix2->r2c1 + matrix1->r3c3 * matrix2->r3c1;
+ const float r3c2 = matrix1->r3c1 * matrix2->r1c2 + matrix1->r3c2 * matrix2->r2c2 + matrix1->r3c3 * matrix2->r3c2;
+
+ result->r1c1 = r1c1;
+ result->r1c2 = r1c2;
+
+ result->r2c1 = r2c1;
+ result->r2c2 = r2c2;
+
+ result->r3c1 = r3c1;
+ result->r3c2 = r3c2;
+}
+
+void bg_fp64_matrix_product_3x3_at_2x3(const BgFP64Matrix3x3* matrix1, const BgFP64Matrix2x3* matrix2, BgFP64Matrix2x3* result)
+{
+ const double r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1 + matrix1->r1c3 * matrix2->r3c1;
+ const double r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2 + matrix1->r1c3 * matrix2->r3c2;
+
+ const double r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1 + matrix1->r2c3 * matrix2->r3c1;
+ const double r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2 + matrix1->r2c3 * matrix2->r3c2;
+
+ const double r3c1 = matrix1->r3c1 * matrix2->r1c1 + matrix1->r3c2 * matrix2->r2c1 + matrix1->r3c3 * matrix2->r3c1;
+ const double r3c2 = matrix1->r3c1 * matrix2->r1c2 + matrix1->r3c2 * matrix2->r2c2 + matrix1->r3c3 * matrix2->r3c2;
+
+ result->r1c1 = r1c1;
+ result->r1c2 = r1c2;
+
+ result->r2c1 = r2c1;
+ result->r2c2 = r2c2;
+
+ result->r3c1 = r3c1;
+ result->r3c2 = r3c2;
+}
+
+// ========== Matrix Product 3x3 at 3x3 ========= //
+
+void bg_fp32_matrix_product_3x3_at_3x3(const BgFP32Matrix3x3* matrix1, const BgFP32Matrix3x3* matrix2, BgFP32Matrix3x3* result)
+{
+ const float r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1 + matrix1->r1c3 * matrix2->r3c1;
+ const float r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2 + matrix1->r1c3 * matrix2->r3c2;
+ const float r1c3 = matrix1->r1c1 * matrix2->r1c3 + matrix1->r1c2 * matrix2->r2c3 + matrix1->r1c3 * matrix2->r3c3;
+
+ const float r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1 + matrix1->r2c3 * matrix2->r3c1;
+ const float r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2 + matrix1->r2c3 * matrix2->r3c2;
+ const float r2c3 = matrix1->r2c1 * matrix2->r1c3 + matrix1->r2c2 * matrix2->r2c3 + matrix1->r2c3 * matrix2->r3c3;
+
+ const float r3c1 = matrix1->r3c1 * matrix2->r1c1 + matrix1->r3c2 * matrix2->r2c1 + matrix1->r3c3 * matrix2->r3c1;
+ const float r3c2 = matrix1->r3c1 * matrix2->r1c2 + matrix1->r3c2 * matrix2->r2c2 + matrix1->r3c3 * matrix2->r3c2;
+ const float r3c3 = matrix1->r3c1 * matrix2->r1c3 + matrix1->r3c2 * matrix2->r2c3 + matrix1->r3c3 * matrix2->r3c3;
+
+ result->r1c1 = r1c1;
+ result->r1c2 = r1c2;
+ result->r1c3 = r1c3;
+
+ result->r2c1 = r2c1;
+ result->r2c2 = r2c2;
+ result->r2c3 = r2c3;
+
+ result->r3c1 = r3c1;
+ result->r3c2 = r3c2;
+ result->r3c3 = r3c3;
+}
+
+void bg_fp64_matrix_product_3x3_at_3x3(const BgFP64Matrix3x3* matrix1, const BgFP64Matrix3x3* matrix2, BgFP64Matrix3x3* result)
+{
+ const double r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1 + matrix1->r1c3 * matrix2->r3c1;
+ const double r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2 + matrix1->r1c3 * matrix2->r3c2;
+ const double r1c3 = matrix1->r1c1 * matrix2->r1c3 + matrix1->r1c2 * matrix2->r2c3 + matrix1->r1c3 * matrix2->r3c3;
+
+ const double r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1 + matrix1->r2c3 * matrix2->r3c1;
+ const double r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2 + matrix1->r2c3 * matrix2->r3c2;
+ const double r2c3 = matrix1->r2c1 * matrix2->r1c3 + matrix1->r2c2 * matrix2->r2c3 + matrix1->r2c3 * matrix2->r3c3;
+
+ const double r3c1 = matrix1->r3c1 * matrix2->r1c1 + matrix1->r3c2 * matrix2->r2c1 + matrix1->r3c3 * matrix2->r3c1;
+ const double r3c2 = matrix1->r3c1 * matrix2->r1c2 + matrix1->r3c2 * matrix2->r2c2 + matrix1->r3c3 * matrix2->r3c2;
+ const double r3c3 = matrix1->r3c1 * matrix2->r1c3 + matrix1->r3c2 * matrix2->r2c3 + matrix1->r3c3 * matrix2->r3c3;
+
+ result->r1c1 = r1c1;
+ result->r1c2 = r1c2;
+ result->r1c3 = r1c3;
+
+ result->r2c1 = r2c1;
+ result->r2c2 = r2c2;
+ result->r2c3 = r2c3;
+
+ result->r3c1 = r3c1;
+ result->r3c2 = r3c2;
+ result->r3c3 = r3c3;
+}
diff --git a/basic-geometry/matrixes.h b/basic-geometry/matrixes.h
new file mode 100644
index 0000000..f448770
--- /dev/null
+++ b/basic-geometry/matrixes.h
@@ -0,0 +1,130 @@
+#ifndef _GEOMETRY_MATRIX_TYPES_H_
+#define _GEOMETRY_MATRIX_TYPES_H_
+
+// ================== Matrix2x2 ================= //
+
+typedef struct {
+ float r1c1, r1c2;
+ float r2c1, r2c2;
+} BgFP32Matrix2x2;
+
+typedef struct {
+ double r1c1, r1c2;
+ double r2c1, r2c2;
+} BgFP64Matrix2x2;
+
+// ================== Matrix2x3 ================= //
+
+typedef struct {
+ float r1c1, r1c2;
+ float r2c1, r2c2;
+ float r3c1, r3c2;
+} BgFP32Matrix2x3;
+
+typedef struct {
+ double r1c1, r1c2;
+ double r2c1, r2c2;
+ double r3c1, r3c2;
+} BgFP64Matrix2x3;
+
+// ================== Matrix3x2 ================= //
+
+typedef struct {
+ float r1c1, r1c2, r1c3;
+ float r2c1, r2c2, r2c3;
+} BgFP32Matrix3x2;
+
+typedef struct {
+ double r1c1, r1c2, r1c3;
+ double r2c1, r2c2, r2c3;
+} BgFP64Matrix3x2;
+
+// ================== Matrix3x3 ================= //
+
+typedef struct {
+ float r1c1, r1c2, r1c3;
+ float r2c1, r2c2, r2c3;
+ float r3c1, r3c2, r3c3;
+} BgFP32Matrix3x3;
+
+typedef struct {
+ double r1c1, r1c2, r1c3;
+ double r2c1, r2c2, r2c3;
+ double r3c1, r3c2, r3c3;
+} BgFP64Matrix3x3;
+
+// ========== Matrix Product 2x2 at 2x2 ========= //
+
+static inline void bg_fp32_matrix_product_2x2_at_2x2(const BgFP32Matrix2x2* matrix1, const BgFP32Matrix2x2* matrix2, BgFP32Matrix2x2* result)
+{
+ const float r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1;
+ const float r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2;
+
+ const float r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1;
+ const float r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2;
+
+ result->r1c1 = r1c1;
+ result->r1c2 = r1c2;
+
+ result->r2c1 = r2c1;
+ result->r2c2 = r2c2;
+}
+
+static inline void bg_fp64_matrix_product_2x2_at_2x2(const BgFP64Matrix2x2* matrix1, const BgFP64Matrix2x2* matrix2, BgFP64Matrix2x2* result)
+{
+ const double r1c1 = matrix1->r1c1 * matrix2->r1c1 + matrix1->r1c2 * matrix2->r2c1;
+ const double r1c2 = matrix1->r1c1 * matrix2->r1c2 + matrix1->r1c2 * matrix2->r2c2;
+
+ const double r2c1 = matrix1->r2c1 * matrix2->r1c1 + matrix1->r2c2 * matrix2->r2c1;
+ const double r2c2 = matrix1->r2c1 * matrix2->r1c2 + matrix1->r2c2 * matrix2->r2c2;
+
+ result->r1c1 = r1c1;
+ result->r1c2 = r1c2;
+
+ result->r2c1 = r2c1;
+ result->r2c2 = r2c2;
+}
+
+// ========== Matrix Product 2x2 at 3x2 ========= //
+
+void bg_fp32_matrix_product_2x2_at_3x2(const BgFP32Matrix2x2* matrix1, const BgFP32Matrix3x2* matrix2, BgFP32Matrix3x2* result);
+
+void bg_fp64_matrix_product_2x2_at_3x2(const BgFP64Matrix2x2* matrix1, const BgFP64Matrix3x2* matrix2, BgFP64Matrix3x2* result);
+
+// ========== Matrix Product 2x3 at 2x2 ========= //
+
+void bg_fp32_matrix_product_2x3_at_2x2(const BgFP32Matrix2x3* matrix1, const BgFP32Matrix2x2* matrix2, BgFP32Matrix2x3* result);
+
+void bg_fp64_matrix_product_2x3_at_2x2(const BgFP64Matrix2x3* matrix1, const BgFP64Matrix2x2* matrix2, BgFP64Matrix2x3* result);
+
+// ========== Matrix Product 2x3 at 3x2 ========= //
+
+void bg_fp32_matrix_product_2x3_at_3x2(const BgFP32Matrix2x3* matrix1, const BgFP32Matrix3x2* matrix2, BgFP32Matrix3x3* result);
+
+void bg_fp64_matrix_product_2x3_at_3x2(const BgFP64Matrix2x3* matrix1, const BgFP64Matrix3x2* matrix2, BgFP64Matrix3x3* result);
+
+// ========== Matrix Product 3x2 at 2x3 ========= //
+
+void bg_fp32_matrix_product_3x2_at_2x3(const BgFP32Matrix3x2* matrix1, const BgFP32Matrix2x3* matrix2, BgFP32Matrix2x2* result);
+
+void bg_fp64_matrix_product_3x2_at_2x3(const BgFP64Matrix3x2* matrix1, const BgFP64Matrix2x3* matrix2, BgFP64Matrix2x2* result);
+
+// ========== Matrix Product 3x2 at 3x3 ========= //
+
+void bg_fp32_matrix_product_3x2_at_3x3(const BgFP32Matrix3x2* matrix1, const BgFP32Matrix3x3* matrix2, BgFP32Matrix3x2* result);
+
+void bg_fp64_matrix_product_3x2_at_3x3(const BgFP64Matrix3x2* matrix1, const BgFP64Matrix3x3* matrix2, BgFP64Matrix3x2* result);
+
+// ========== Matrix Product 3x3 at 2x3 ========= //
+
+void bg_fp32_matrix_product_3x3_at_2x3(const BgFP32Matrix3x3* matrix1, const BgFP32Matrix2x3* matrix2, BgFP32Matrix2x3* result);
+
+void bg_fp64_matrix_product_3x3_at_2x3(const BgFP64Matrix3x3* matrix1, const BgFP64Matrix2x3* matrix2, BgFP64Matrix2x3* result);
+
+// ========== Matrix Product 3x3 at 3x3 ========= //
+
+void bg_fp32_matrix_product_3x3_at_3x3(const BgFP32Matrix3x3* matrix1, const BgFP32Matrix3x3* matrix2, BgFP32Matrix3x3* result);
+
+void bg_fp64_matrix_product_3x3_at_3x3(const BgFP64Matrix3x3* matrix1, const BgFP64Matrix3x3* matrix2, BgFP64Matrix3x3* result);
+
+#endif // _GEOMETRY_MATRIX_TYPES_H_
diff --git a/basic-geometry/quaternion.c b/basic-geometry/quaternion.c
new file mode 100644
index 0000000..a937eb3
--- /dev/null
+++ b/basic-geometry/quaternion.c
@@ -0,0 +1,157 @@
+#include "quaternion.h"
+
+// ============ Make Rotation Matrix ============ //
+
+void bg_fp32_quaternion_get_rotation_matrix(const BgFP32Quaternion* quaternion, BgFP32Matrix3x3* matrix)
+{
+ const float s0s0 = quaternion->s0 * quaternion->s0;
+ const float x1x1 = quaternion->x1 * quaternion->x1;
+ const float x2x2 = quaternion->x2 * quaternion->x2;
+ const float x3x3 = quaternion->x3 * quaternion->x3;
+
+ const float square_module = (s0s0 + x1x1) + (x2x2 + x3x3);
+
+ if (-BG_FP32_EPSYLON <= square_module && square_module <= BG_FP32_EPSYLON)
+ {
+ bg_fp32_matrix3x3_set_to_identity(matrix);
+ return;
+ }
+
+ const float corrector1 = 1.0f / square_module;
+ const float corrector2 = 2.0f * corrector1;
+
+ const float s0x1 = quaternion->s0 * quaternion->x1;
+ const float s0x2 = quaternion->s0 * quaternion->x2;
+ const float s0x3 = quaternion->s0 * quaternion->x3;
+ const float x1x2 = quaternion->x1 * quaternion->x2;
+ const float x1x3 = quaternion->x1 * quaternion->x3;
+ const float x2x3 = quaternion->x2 * quaternion->x3;
+
+ matrix->r1c1 = corrector1 * ((s0s0 + x1x1) - (x2x2 + x3x3));
+ matrix->r2c2 = corrector1 * ((s0s0 + x2x2) - (x1x1 + x3x3));
+ matrix->r3c3 = corrector1 * ((s0s0 + x3x3) - (x1x1 + x2x2));
+
+ matrix->r1c2 = corrector2 * (x1x2 - s0x3);
+ matrix->r2c3 = corrector2 * (x2x3 - s0x1);
+ matrix->r3c1 = corrector2 * (x1x3 - s0x2);
+
+ matrix->r2c1 = corrector2 * (x1x2 + s0x3);
+ matrix->r3c2 = corrector2 * (x2x3 + s0x1);
+ matrix->r1c3 = corrector2 * (x1x3 + s0x2);
+}
+
+void bg_fp64_quaternion_get_rotation_matrix(const BgFP64Quaternion* quaternion, BgFP64Matrix3x3* matrix)
+{
+ const double s0s0 = quaternion->s0 * quaternion->s0;
+ const double x1x1 = quaternion->x1 * quaternion->x1;
+ const double x2x2 = quaternion->x2 * quaternion->x2;
+ const double x3x3 = quaternion->x3 * quaternion->x3;
+
+ const double square_module = (s0s0 + x1x1) + (x2x2 + x3x3);
+
+ if (-BG_FP64_EPSYLON <= square_module && square_module <= BG_FP64_EPSYLON)
+ {
+ bg_fp64_matrix3x3_set_to_identity(matrix);
+ return;
+ }
+
+ const double corrector1 = 1.0f / square_module;
+ const double corrector2 = 2.0f * corrector1;
+
+ const double s0x1 = quaternion->s0 * quaternion->x1;
+ const double s0x2 = quaternion->s0 * quaternion->x2;
+ const double s0x3 = quaternion->s0 * quaternion->x3;
+ const double x1x2 = quaternion->x1 * quaternion->x2;
+ const double x1x3 = quaternion->x1 * quaternion->x3;
+ const double x2x3 = quaternion->x2 * quaternion->x3;
+
+ matrix->r1c1 = corrector1 * ((s0s0 + x1x1) - (x2x2 + x3x3));
+ matrix->r2c2 = corrector1 * ((s0s0 + x2x2) - (x1x1 + x3x3));
+ matrix->r3c3 = corrector1 * ((s0s0 + x3x3) - (x1x1 + x2x2));
+
+ matrix->r1c2 = corrector2 * (x1x2 - s0x3);
+ matrix->r2c3 = corrector2 * (x2x3 - s0x1);
+ matrix->r3c1 = corrector2 * (x1x3 - s0x2);
+
+ matrix->r2c1 = corrector2 * (x1x2 + s0x3);
+ matrix->r3c2 = corrector2 * (x2x3 + s0x1);
+ matrix->r1c3 = corrector2 * (x1x3 + s0x2);
+}
+
+// ============ Make Reverse Matrix ============= //
+
+void bg_fp32_quaternion_get_reverse_matrix(const BgFP32Quaternion* quaternion, BgFP32Matrix3x3* matrix)
+{
+ const float s0s0 = quaternion->s0 * quaternion->s0;
+ const float x1x1 = quaternion->x1 * quaternion->x1;
+ const float x2x2 = quaternion->x2 * quaternion->x2;
+ const float x3x3 = quaternion->x3 * quaternion->x3;
+
+ const float square_module = (s0s0 + x1x1) + (x2x2 + x3x3);
+
+ if (-BG_FP32_EPSYLON <= square_module && square_module <= BG_FP32_EPSYLON)
+ {
+ bg_fp32_matrix3x3_set_to_identity(matrix);
+ return;
+ }
+
+ const float corrector1 = 1.0f / square_module;
+ const float corrector2 = 2.0f * corrector1;
+
+ const float s0x1 = quaternion->s0 * quaternion->x1;
+ const float s0x2 = quaternion->s0 * quaternion->x2;
+ const float s0x3 = quaternion->s0 * quaternion->x3;
+ const float x1x2 = quaternion->x1 * quaternion->x2;
+ const float x1x3 = quaternion->x1 * quaternion->x3;
+ const float x2x3 = quaternion->x2 * quaternion->x3;
+
+ matrix->r1c1 = corrector1 * ((s0s0 + x1x1) - (x2x2 + x3x3));
+ matrix->r2c2 = corrector1 * ((s0s0 + x2x2) - (x1x1 + x3x3));
+ matrix->r3c3 = corrector1 * ((s0s0 + x3x3) - (x1x1 + x2x2));
+
+ matrix->r1c2 = corrector2 * (x1x2 + s0x3);
+ matrix->r2c3 = corrector2 * (x2x3 + s0x1);
+ matrix->r3c1 = corrector2 * (x1x3 + s0x2);
+
+ matrix->r2c1 = corrector2 * (x1x2 - s0x3);
+ matrix->r3c2 = corrector2 * (x2x3 - s0x1);
+ matrix->r1c3 = corrector2 * (x1x3 - s0x2);
+}
+
+void bg_fp64_quaternion_get_reverse_matrix(const BgFP64Quaternion* quaternion, BgFP64Matrix3x3* matrix)
+{
+ const double s0s0 = quaternion->s0 * quaternion->s0;
+ const double x1x1 = quaternion->x1 * quaternion->x1;
+ const double x2x2 = quaternion->x2 * quaternion->x2;
+ const double x3x3 = quaternion->x3 * quaternion->x3;
+
+ const double square_module = (s0s0 + x1x1) + (x2x2 + x3x3);
+
+ if (-BG_FP64_EPSYLON <= square_module && square_module <= BG_FP64_EPSYLON)
+ {
+ bg_fp64_matrix3x3_set_to_identity(matrix);
+ return;
+ }
+
+ const double corrector1 = 1.0f / square_module;
+ const double corrector2 = 2.0f * corrector1;
+
+ const double s0x1 = quaternion->s0 * quaternion->x1;
+ const double s0x2 = quaternion->s0 * quaternion->x2;
+ const double s0x3 = quaternion->s0 * quaternion->x3;
+ const double x1x2 = quaternion->x1 * quaternion->x2;
+ const double x1x3 = quaternion->x1 * quaternion->x3;
+ const double x2x3 = quaternion->x2 * quaternion->x3;
+
+ matrix->r1c1 = corrector1 * ((s0s0 + x1x1) - (x2x2 + x3x3));
+ matrix->r2c2 = corrector1 * ((s0s0 + x2x2) - (x1x1 + x3x3));
+ matrix->r3c3 = corrector1 * ((s0s0 + x3x3) - (x1x1 + x2x2));
+
+ matrix->r1c2 = corrector2 * (x1x2 + s0x3);
+ matrix->r2c3 = corrector2 * (x2x3 + s0x1);
+ matrix->r3c1 = corrector2 * (x1x3 + s0x2);
+
+ matrix->r2c1 = corrector2 * (x1x2 - s0x3);
+ matrix->r3c2 = corrector2 * (x2x3 - s0x1);
+ matrix->r1c3 = corrector2 * (x1x3 - s0x2);
+}
diff --git a/basic-geometry/quaternion.h b/basic-geometry/quaternion.h
new file mode 100644
index 0000000..a44207a
--- /dev/null
+++ b/basic-geometry/quaternion.h
@@ -0,0 +1,235 @@
+#ifndef _GEOMETRY_QUATERNION_H_
+#define _GEOMETRY_QUATERNION_H_
+
+#include
+
+#include "basis.h"
+#include "matrix3x3.h"
+
+typedef struct {
+ float s0, x1, x2, x3;
+} BgFP32Quaternion;
+
+typedef struct {
+ double s0, x1, x2, x3;
+} BgFP64Quaternion;
+
+// ==================== Reset =================== //
+
+static inline void bg_fp32_quaternion_reset(BgFP32Quaternion * quaternion)
+{
+ quaternion->s0 = 0.0f;
+ quaternion->x1 = 0.0f;
+ quaternion->x2 = 0.0f;
+ quaternion->x3 = 0.0f;
+}
+
+static inline void bg_fp64_quaternion_reset(BgFP64Quaternion * quaternion)
+{
+ quaternion->s0 = 0.0;
+ quaternion->x1 = 0.0;
+ quaternion->x2 = 0.0;
+ quaternion->x3 = 0.0;
+}
+
+// ================== Set Unit ================== //
+
+static inline void bg_fp32_quaternion_set_identity(BgFP32Quaternion * quaternion)
+{
+ quaternion->s0 = 1.0f;
+ quaternion->x1 = 0.0f;
+ quaternion->x2 = 0.0f;
+ quaternion->x3 = 0.0f;
+}
+
+static inline void bg_fp64_quaternion_set_identity(BgFP64Quaternion * quaternion)
+{
+ quaternion->s0 = 1.0;
+ quaternion->x1 = 0.0;
+ quaternion->x2 = 0.0;
+ quaternion->x3 = 0.0;
+}
+
+// ==================== Set ===================== //
+
+static inline void bg_fp32_quaternion_set_values(const float s0, const float x1, const float x2, const float x3, BgFP32Quaternion * quaternion)
+{
+ quaternion->s0 = s0;
+ quaternion->x1 = x1;
+ quaternion->x2 = x2;
+ quaternion->x3 = x3;
+}
+
+static inline void bg_fp64_quaternion_set_values(const double s0, const double x1, const double x2, const double x3, BgFP64Quaternion * quaternion)
+{
+ quaternion->s0 = s0;
+ quaternion->x1 = x1;
+ quaternion->x2 = x2;
+ quaternion->x3 = x3;
+}
+
+// ==================== Copy ==================== //
+
+static inline void bg_fp32_quaternion_copy(const BgFP32Quaternion* from, BgFP32Quaternion* to)
+{
+ to->s0 = from->s0;
+ to->x1 = from->x1;
+ to->x2 = from->x2;
+ to->x3 = from->x3;
+}
+
+static inline void bg_fp64_quaternion_copy(const BgFP64Quaternion* from, BgFP64Quaternion* to)
+{
+ to->s0 = from->s0;
+ to->x1 = from->x1;
+ to->x2 = from->x2;
+ to->x3 = from->x3;
+}
+
+// ============= Copy to twin type ============== //
+
+static inline void bg_fp32_quaternion_set_from_fp64(const BgFP64Quaternion* versor, BgFP32Quaternion* result)
+{
+ result->s0 = (float) versor->s0;
+ result->x1 = (float) versor->x1;
+ result->x2 = (float) versor->x2;
+ result->x3 = (float) versor->x3;
+}
+
+static inline void bg_fp64_quaternion_set_from_fp32(const BgFP32Quaternion* versor, BgFP64Quaternion* result)
+{
+ result->s0 = versor->s0;
+ result->x1 = versor->x1;
+ result->x2 = versor->x2;
+ result->x3 = versor->x3;
+}
+
+// ================= Inversion ================== //
+
+static inline void bg_fp32_quaternion_conjugate(BgFP32Quaternion* versor)
+{
+ versor->x1 = -versor->x1;
+ versor->x2 = -versor->x2;
+ versor->x3 = -versor->x3;
+}
+
+static inline void bg_fp64_quaternion_conjugate(BgFP64Quaternion* versor)
+{
+ versor->x1 = -versor->x1;
+ versor->x2 = -versor->x2;
+ versor->x3 = -versor->x3;
+}
+
+// ================ Set Conjugate =============== //
+
+static inline void bg_fp32_quaternion_set_conjugate(const BgFP32Quaternion* versor, BgFP32Quaternion* result)
+{
+ result->s0 = versor->s0;
+ result->x1 = -versor->x1;
+ result->x2 = -versor->x2;
+ result->x3 = -versor->x3;
+}
+
+static inline void bg_fp64_quaternion_set_conjugate(const BgFP64Quaternion* versor, BgFP64Quaternion* result)
+{
+ result->s0 = versor->s0;
+ result->x1 = -versor->x1;
+ result->x2 = -versor->x2;
+ result->x3 = -versor->x3;
+}
+
+// ================ Get Inverted ================ //
+
+static inline void bg_fp32_quaternion_set_conjugate_fp64(const BgFP64Quaternion* versor, BgFP32Quaternion* result)
+{
+ result->s0 = (float) versor->s0;
+ result->x1 = (float) -versor->x1;
+ result->x2 = (float) -versor->x2;
+ result->x3 = (float) -versor->x3;
+}
+
+static inline void bg_fp64_quaternion_set_conjugate_fp32(const BgFP32Quaternion* versor, BgFP64Quaternion* result)
+{
+ result->s0 = versor->s0;
+ result->x1 = -versor->x1;
+ result->x2 = -versor->x2;
+ result->x3 = -versor->x3;
+}
+
+// ============ Make Rotation Matrix ============ //
+
+void bg_fp32_quaternion_get_rotation_matrix(const BgFP32Quaternion* quaternion, BgFP32Matrix3x3* matrix);
+
+void bg_fp64_quaternion_get_rotation_matrix(const BgFP64Quaternion* quaternion, BgFP64Matrix3x3* matrix);
+
+// ============ Make Reverse Matrix ============= //
+
+void bg_fp32_quaternion_get_reverse_matrix(const BgFP32Quaternion* quaternion, BgFP32Matrix3x3* matrix);
+
+void bg_fp64_quaternion_get_reverse_matrix(const BgFP64Quaternion* quaternion, BgFP64Matrix3x3* matrix);
+
+// ==================== Add ===================== //
+
+static inline void bg_fp32_quaternion_add(const BgFP32Quaternion * quaternion1, const BgFP32Quaternion * quaternion2, BgFP32Quaternion * result)
+{
+ result->s0 = quaternion1->s0 + quaternion2->s0;
+ result->x1 = quaternion1->x1 + quaternion2->x1;
+ result->x2 = quaternion1->x2 + quaternion2->x2;
+ result->x3 = quaternion1->x3 + quaternion2->x3;
+}
+
+static inline void bg_fp64_quaternion_add(const BgFP64Quaternion * quaternion1, const BgFP64Quaternion * quaternion2, BgFP64Quaternion * result)
+{
+ result->s0 = quaternion1->s0 + quaternion2->s0;
+ result->x1 = quaternion1->x1 + quaternion2->x1;
+ result->x2 = quaternion1->x2 + quaternion2->x2;
+ result->x3 = quaternion1->x3 + quaternion2->x3;
+}
+
+// ================== Subtract ================== //
+
+static inline void bg_fp32_quaternion_subtract(const BgFP32Quaternion * minuend, const BgFP32Quaternion * subtrahend, BgFP32Quaternion * result)
+{
+ result->s0 = minuend->s0 - subtrahend->s0;
+ result->x1 = minuend->x1 - subtrahend->x1;
+ result->x2 = minuend->x2 - subtrahend->x2;
+ result->x3 = minuend->x3 - subtrahend->x3;
+}
+
+static inline void bg_fp64_quaternion_subtract(const BgFP64Quaternion * minuend, const BgFP64Quaternion * subtrahend, BgFP64Quaternion * result)
+{
+ result->s0 = minuend->s0 - subtrahend->s0;
+ result->x1 = minuend->x1 - subtrahend->x1;
+ result->x2 = minuend->x2 - subtrahend->x2;
+ result->x3 = minuend->x3 - subtrahend->x3;
+}
+
+// =============== Multiplication =============== //
+
+static inline void bg_fp32_quaternion_multiply(const BgFP32Quaternion* left, const BgFP32Quaternion* right, BgFP32Quaternion* result)
+{
+ const float s0 = (left->s0 * right->s0 - left->x1 * right->x1) - (left->x2 * right->x2 + left->x3 * right->x3);
+ const float x1 = (left->x1 * right->s0 + left->s0 * right->x1) - (left->x3 * right->x2 - left->x2 * right->x3);
+ const float x2 = (left->x2 * right->s0 + left->s0 * right->x2) - (left->x1 * right->x3 - left->x3 * right->x1);
+ const float x3 = (left->x3 * right->s0 + left->s0 * right->x3) - (left->x2 * right->x1 - left->x1 * right->x2);
+
+ result->s0 = s0;
+ result->x1 = x1;
+ result->x2 = x2;
+ result->x3 = x3;
+}
+
+static inline void bg_fp64_quaternion_multiply(const BgFP64Quaternion* left, const BgFP64Quaternion* right, BgFP64Quaternion* result)
+{
+ const double s0 = (left->s0 * right->s0 - left->x1 * right->x1) - (left->x2 * right->x2 + left->x3 * right->x3);
+ const double x1 = (left->x1 * right->s0 + left->s0 * right->x1) - (left->x3 * right->x2 - left->x2 * right->x3);
+ const double x2 = (left->x2 * right->s0 + left->s0 * right->x2) - (left->x1 * right->x3 - left->x3 * right->x1);
+ const double x3 = (left->x3 * right->s0 + left->s0 * right->x3) - (left->x2 * right->x1 - left->x1 * right->x2);
+
+ result->s0 = s0;
+ result->x1 = x1;
+ result->x2 = x2;
+ result->x3 = x3;
+}
+
+#endif // _GEOMETRY_QUATERNION_H_
diff --git a/basic-geometry/rotation3.c b/basic-geometry/rotation3.c
new file mode 100644
index 0000000..e550206
--- /dev/null
+++ b/basic-geometry/rotation3.c
@@ -0,0 +1,5 @@
+#include "rotation3.h"
+
+const BgFP32Rotation3 BG_FP32_IDLE_ROTATION3 = { {0.0f, 0.0f, 0.0f}, 0.0f};
+
+const BgFP64Rotation3 BG_FP64_IDLE_ROTATION3 = { {0.0, 0.0, 0.0}, 0.0};
diff --git a/basic-geometry/rotation3.h b/basic-geometry/rotation3.h
new file mode 100644
index 0000000..0733e58
--- /dev/null
+++ b/basic-geometry/rotation3.h
@@ -0,0 +1,101 @@
+#ifndef _GEOMETRY_ROTATION3_H_
+#define _GEOMETRY_ROTATION3_H_
+
+#include "basis.h"
+#include "angle.h"
+#include "vector3.h"
+
+typedef struct {
+ BgFP32Vector3 axis;
+ float radians;
+} BgFP32Rotation3;
+
+typedef struct {
+ BgFP64Vector3 axis;
+ double radians;
+} BgFP64Rotation3;
+
+extern const BgFP32Rotation3 BG_FP32_IDLE_ROTATION3;
+
+extern const BgFP64Rotation3 BG_FP64_IDLE_ROTATION3;
+
+// =================== Reset ==================== //
+
+static inline void bg_fp32_rotation_reset(BgFP32Rotation3* rotation)
+{
+ rotation->axis.x1 = 0.0f;
+ rotation->axis.x2 = 0.0f;
+ rotation->axis.x3 = 0.0f;
+
+ rotation->radians = 0.0f;
+}
+
+static inline void bg_fp64_rotation_reset(BgFP64Rotation3* rotation)
+{
+ rotation->axis.x1 = 0.0;
+ rotation->axis.x2 = 0.0;
+ rotation->axis.x3 = 0.0;
+
+ rotation->radians = 0.0;
+}
+
+// ==================== Make ==================== //
+
+static inline void bg_fp32_rotation_set_values(const float x1, const float x2, const float x3, const float angle, const angle_unit_t unit, BgFP32Rotation3* rotation)
+{
+ rotation->axis.x1 = x1;
+ rotation->axis.x2 = x2;
+ rotation->axis.x3 = x3;
+
+ if (bg_fp32_vector3_normalize(&rotation->axis)) {
+ rotation->radians = bg_fp32_angle_to_radians(angle, unit);
+ }
+ else {
+ rotation->radians = 0.0f;
+ }
+}
+
+
+static inline void bg_fp64_rotation_set_values(const double x1, const double x2, const double x3, const double angle, const angle_unit_t unit, BgFP64Rotation3* rotation)
+{
+ rotation->axis.x1 = x1;
+ rotation->axis.x2 = x2;
+ rotation->axis.x3 = x3;
+
+ if (bg_fp64_vector3_normalize(&rotation->axis)) {
+ rotation->radians = bg_fp64_angle_to_radians(angle, unit);
+ }
+ else {
+ rotation->radians = 0.0;
+ }
+}
+
+static inline void bg_fp32_rotation_set_with_axis(const BgFP32Vector3* axis, const float angle, const angle_unit_t unit, BgFP32Rotation3* rotation)
+{
+ rotation->axis.x1 = axis->x1;
+ rotation->axis.x2 = axis->x2;
+ rotation->axis.x3 = axis->x3;
+
+ if (bg_fp32_vector3_normalize(&rotation->axis)) {
+ rotation->radians = bg_fp32_angle_to_radians(angle, unit);
+ }
+ else {
+ rotation->radians = 0.0f;
+ }
+}
+
+static inline void bg_fp64_rotation_set_with_axis(const BgFP64Vector3* axis, const double angle, const angle_unit_t unit, BgFP64Rotation3* rotation)
+{
+ rotation->axis.x1 = axis->x1;
+ rotation->axis.x2 = axis->x2;
+ rotation->axis.x3 = axis->x3;
+
+ if (bg_fp64_vector3_normalize(&rotation->axis)) {
+ rotation->radians = bg_fp64_angle_to_radians(angle, unit);
+ }
+ else {
+ rotation->radians = 0.0;
+ }
+}
+
+#endif
diff --git a/basic-geometry/vector2.c b/basic-geometry/vector2.c
new file mode 100644
index 0000000..145dd0c
--- /dev/null
+++ b/basic-geometry/vector2.c
@@ -0,0 +1,65 @@
+#include "vector2.h"
+
+// =================== Angle ==================== //
+
+float bg_fp32_vector2_get_angle(const BgFP32Vector2* vector1, const BgFP32Vector2* vector2, const angle_unit_t unit)
+{
+ if (vector1 == 0 || vector2 == 0) {
+ return 0.0f;
+ }
+
+ const float square_module1 = bg_fp32_vector2_get_square_module(vector1);
+
+ if (square_module1 <= BG_FP32_SQUARE_EPSYLON) {
+ return 0.0f;
+ }
+
+ const float square_module2 = bg_fp32_vector2_get_square_module(vector2);
+
+ if (square_module2 <= BG_FP32_SQUARE_EPSYLON) {
+ return 0.0f;
+ }
+
+ const float cosine = bg_fp32_vector2_dot_product(vector1, vector2) / sqrtf(square_module1 * square_module2);
+
+ if (cosine >= 1.0f - BG_FP32_EPSYLON) {
+ return 0.0f;
+ }
+
+ if (cosine <= -1.0f + BG_FP32_EPSYLON) {
+ return bg_fp32_angle_get_half_circle(unit);
+ }
+
+ return bg_fp32_radians_to_units(acosf(cosine), unit);
+}
+
+double bg_fp64_vector2_get_angle(const BgFP64Vector2* vector1, const BgFP64Vector2* vector2, const angle_unit_t unit)
+{
+ if (vector1 == 0 || vector2 == 0) {
+ return 0.0;
+ }
+
+ const double square_module1 = bg_fp64_vector2_get_square_module(vector1);
+
+ if (square_module1 <= BG_FP64_SQUARE_EPSYLON) {
+ return 0.0;
+ }
+
+ const double square_module2 = bg_fp64_vector2_get_square_module(vector2);
+
+ if (square_module2 <= BG_FP64_SQUARE_EPSYLON) {
+ return 0.0;
+ }
+
+ const double cosine = bg_fp64_vector2_dot_product(vector1, vector2) / sqrt(square_module1 * square_module2);
+
+ if (cosine >= 1.0 - BG_FP64_EPSYLON) {
+ return 0.0;
+ }
+
+ if (cosine <= -1.0 + BG_FP64_EPSYLON) {
+ return bg_fp64_angle_get_half_circle(unit);
+ }
+
+ return bg_fp64_radians_to_units(acos(cosine), unit);
+}
diff --git a/basic-geometry/vector2.h b/basic-geometry/vector2.h
new file mode 100644
index 0000000..36178d2
--- /dev/null
+++ b/basic-geometry/vector2.h
@@ -0,0 +1,397 @@
+#ifndef _GEOMETRY_VECTOR2_H_
+#define _GEOMETRY_VECTOR2_H_
+
+#include "basis.h"
+#include "angle.h"
+
+#include
+
+typedef struct
+{
+ float x1, x2;
+} BgFP32Vector2;
+
+typedef struct
+{
+ double x1, x2;
+} BgFP64Vector2;
+
+// =================== Reset ==================== //
+
+static inline void bg_fp32_vector2_reset(BgFP32Vector2* vector)
+{
+ vector->x1 = 0.0f;
+ vector->x2 = 0.0f;
+}
+
+static inline void bg_fp64_vector2_reset(BgFP64Vector2* vector)
+{
+ vector->x1 = 0.0;
+ vector->x2 = 0.0;
+}
+
+// ==================== Set ===================== //
+
+static inline void bg_fp32_vector2_set_values(const float x1, const float x2, BgFP32Vector2* to)
+{
+ to->x1 = x1;
+ to->x2 = x2;
+}
+
+static inline void bg_fp64_vector2_set_values(const double x1, const double x2, BgFP64Vector2* to)
+{
+ to->x1 = x1;
+ to->x2 = x2;
+}
+
+// ==================== Copy ==================== //
+
+static inline void bg_fp32_vector2_copy(const BgFP32Vector2* from, BgFP32Vector2* to)
+{
+ to->x1 = from->x1;
+ to->x2 = from->x2;
+}
+
+static inline void bg_fp64_vector2_copy(const BgFP64Vector2* from, BgFP64Vector2* to)
+{
+ to->x1 = from->x1;
+ to->x2 = from->x2;
+}
+
+// ============= Copy to twin type ============== //
+
+static inline void bg_fp32_vector2_set_from_fp64(const BgFP64Vector2* from, BgFP32Vector2* to)
+{
+ to->x1 = (float)from->x1;
+ to->x2 = (float)from->x2;
+}
+
+static inline void bg_fp64_vector2_set_from_fp32(const BgFP32Vector2* from, BgFP64Vector2* to)
+{
+ to->x1 = from->x1;
+ to->x2 = from->x2;
+}
+
+// =================== Reverse ================== //
+
+static inline void bg_fp32_vector2_set_reverse(const BgFP32Vector2* from, BgFP32Vector2* to)
+{
+ to->x1 = -from->x1;
+ to->x2 = -from->x2;
+}
+
+static inline void bg_fp64_vector2_set_reverse(const BgFP64Vector2* from, BgFP64Vector2* to)
+{
+ to->x1 = -from->x1;
+ to->x2 = -from->x2;
+}
+
+// ============= Reverse twin type ============== //
+
+static inline void bg_fp32_vector2_set_reverse_fp64(const BgFP64Vector2* from, BgFP32Vector2* to)
+{
+ to->x1 = (float) -from->x1;
+ to->x2 = (float) -from->x2;
+}
+
+static inline void bg_fp64_vector2_set_reverse_fp32(const BgFP32Vector2* from, BgFP64Vector2* to)
+{
+ to->x1 = -from->x1;
+ to->x2 = -from->x2;
+}
+
+// =================== Module =================== //
+
+static inline float bg_fp32_vector2_get_square_module(const BgFP32Vector2* vector)
+{
+ return vector->x1 * vector->x1 + vector->x2 * vector->x2;
+}
+
+static inline double bg_fp64_vector2_get_square_module(const BgFP64Vector2* vector)
+{
+ return vector->x1 * vector->x1 + vector->x2 * vector->x2;
+}
+
+static inline float bg_fp32_vector2_get_module(const BgFP32Vector2* vector)
+{
+ return sqrtf(bg_fp32_vector2_get_square_module(vector));
+}
+
+static inline double bg_fp64_vector2_get_module(const BgFP64Vector2* vector)
+{
+ return sqrt(bg_fp64_vector2_get_square_module(vector));
+}
+
+// ================= Comparison ================= //
+
+static inline int bg_fp32_vector2_is_zero(const BgFP32Vector2* vector)
+{
+ return bg_fp32_vector2_get_square_module(vector) <= BG_FP32_SQUARE_EPSYLON;
+}
+
+static inline int bg_fp64_vector2_is_zero(const BgFP64Vector2* vector)
+{
+ return bg_fp64_vector2_get_square_module(vector) <= BG_FP64_SQUARE_EPSYLON;
+}
+
+static inline int bg_fp32_vector2_is_unit(const BgFP32Vector2* vector)
+{
+ const float square_module = bg_fp32_vector2_get_square_module(vector);
+
+ return 1.0f - BG_FP32_TWO_EPSYLON <= square_module && square_module <= 1.0f + BG_FP32_TWO_EPSYLON;
+}
+
+static inline int bg_fp64_vector2_is_unit(const BgFP64Vector2* vector)
+{
+ const double square_module = bg_fp64_vector2_get_square_module(vector);
+
+ return 1.0f - BG_FP64_TWO_EPSYLON <= square_module && square_module <= 1.0f + BG_FP64_TWO_EPSYLON;
+}
+
+// ==================== Add ===================== //
+
+static inline void bg_fp32_vector2_add(const BgFP32Vector2* vector1, const BgFP32Vector2* vector2, BgFP32Vector2* result)
+{
+ result->x1 = vector1->x1 + vector2->x1;
+ result->x2 = vector1->x2 + vector2->x2;
+}
+
+static inline void bg_fp64_vector2_add(const BgFP64Vector2* vector1, const BgFP64Vector2* vector2, BgFP64Vector2* result)
+{
+ result->x1 = vector1->x1 + vector2->x1;
+ result->x2 = vector1->x2 + vector2->x2;
+}
+
+// ================ Subtraction ================= //
+
+static inline void bg_fp32_vector2_subtract(const BgFP32Vector2* minuend, const BgFP32Vector2* subtrahend, BgFP32Vector2* result)
+{
+ result->x1 = minuend->x1 - subtrahend->x1;
+ result->x2 = minuend->x2 - subtrahend->x2;
+}
+
+static inline void bg_fp64_vector2_subtract(const BgFP64Vector2* minuend, const BgFP64Vector2* subtrahend, BgFP64Vector2* result)
+{
+ result->x1 = minuend->x1 - subtrahend->x1;
+ result->x2 = minuend->x2 - subtrahend->x2;
+}
+
+// =============== Multiplication =============== //
+
+static inline void bg_fp32_vector2_multiply(const BgFP32Vector2* multiplicand, const float multiplier, BgFP32Vector2* result)
+{
+ result->x1 = multiplicand->x1 * multiplier;
+ result->x2 = multiplicand->x2 * multiplier;
+}
+
+static inline void bg_fp64_vector2_multiply(const BgFP64Vector2* multiplicand, const double multiplier, BgFP64Vector2* result)
+{
+ result->x1 = multiplicand->x1 * multiplier;
+ result->x2 = multiplicand->x2 * multiplier;
+}
+
+// ================== Division ================== //
+
+static inline void bg_fp32_vector2_divide(const BgFP32Vector2* dividend, const float divisor, BgFP32Vector2* result)
+{
+ result->x1 = dividend->x1 / divisor;
+ result->x2 = dividend->x2 / divisor;
+}
+
+static inline void bg_fp64_vector2_divide(const BgFP64Vector2* dividend, const double divisor, BgFP64Vector2* result)
+{
+ result->x1 = dividend->x1 / divisor;
+ result->x2 = dividend->x2 / divisor;
+}
+
+// ================ Append scaled =============== //
+
+static inline void bg_fp32_vector2_append_scaled(BgFP32Vector2* basic_vector, const BgFP32Vector2* scalable_vector, const float scale)
+{
+ basic_vector->x1 += scalable_vector->x1 * scale;
+ basic_vector->x2 += scalable_vector->x2 * scale;
+}
+
+static inline void bg_fp64_vector2_append_scaled(BgFP64Vector2* basic_vector, const BgFP64Vector2* scalable_vector, const double scale)
+{
+ basic_vector->x1 += scalable_vector->x1 * scale;
+ basic_vector->x2 += scalable_vector->x2 * scale;
+}
+
+// ================== Average2 ================== //
+
+static inline void bg_fp32_vector2_get_mean2(const BgFP32Vector2* vector1, const BgFP32Vector2* vector2, BgFP32Vector2* result)
+{
+ result->x1 = (vector1->x1 + vector2->x1) * 0.5f;
+ result->x2 = (vector1->x2 + vector2->x2) * 0.5f;
+}
+
+static inline void bg_fp64_vector2_get_mean2(const BgFP64Vector2* vector1, const BgFP64Vector2* vector2, BgFP64Vector2* result)
+{
+ result->x1 = (vector1->x1 + vector2->x1) * 0.5;
+ result->x2 = (vector1->x2 + vector2->x2) * 0.5;
+}
+
+// ================== Average3 ================== //
+
+static inline void bg_fp32_vector2_get_mean3(const BgFP32Vector2* vector1, const BgFP32Vector2* vector2, const BgFP32Vector2* vector3, BgFP32Vector2* result)
+{
+ result->x1 = (vector1->x1 + vector2->x1 + vector3->x1) * BG_FP32_ONE_THIRD;
+ result->x2 = (vector1->x2 + vector2->x2 + vector3->x2) * BG_FP32_ONE_THIRD;
+}
+
+static inline void bg_fp64_vector2_get_mean3(const BgFP64Vector2* vector1, const BgFP64Vector2* vector2, const BgFP64Vector2* vector3, BgFP64Vector2* result)
+{
+ result->x1 = (vector1->x1 + vector2->x1 + vector3->x1) * BG_FP64_ONE_THIRD;
+ result->x2 = (vector1->x2 + vector2->x2 + vector3->x2) * BG_FP64_ONE_THIRD;
+}
+
+// =============== Scalar Product =============== //
+
+static inline float bg_fp32_vector2_dot_product(const BgFP32Vector2* vector1, const BgFP32Vector2* vector2)
+{
+ return vector1->x1 * vector2->x1 + vector1->x2 * vector2->x2;
+}
+
+static inline double bg_fp64_vector2_dot_product(const BgFP64Vector2* vector1, const BgFP64Vector2* vector2)
+{
+ return vector1->x1 * vector2->x1 + vector1->x2 * vector2->x2;
+}
+
+// =============== Cross Product ================ //
+
+static inline float bg_fp32_vector2_cross_product(const BgFP32Vector2* vector1, const BgFP32Vector2* vector2)
+{
+ return vector1->x1 * vector2->x2 - vector1->x2 * vector2->x1;
+}
+
+static inline double bg_fp64_vector2_cross_product(const BgFP64Vector2* vector1, const BgFP64Vector2* vector2, BgFP64Vector2* result)
+{
+ return vector1->x1 * vector2->x2 - vector1->x2 * vector2->x1;
+}
+
+// =============== Normalization ================ //
+
+static inline int bg_fp32_vector2_normalize(BgFP32Vector2* vector)
+{
+ const float square_module = bg_fp32_vector2_get_square_module(vector);
+
+ if (1.0f - BG_FP32_TWO_EPSYLON <= square_module && square_module <= 1.0f + BG_FP32_TWO_EPSYLON) {
+ return 1;
+ }
+
+ if (square_module <= BG_FP32_SQUARE_EPSYLON) {
+ bg_fp32_vector2_reset(vector);
+ return 0;
+ }
+
+ bg_fp32_vector2_divide(vector, sqrtf(square_module), vector);
+ return 1;
+}
+
+static inline int bg_fp64_vector2_normalize(BgFP64Vector2* vector)
+{
+ const double square_module = bg_fp64_vector2_get_square_module(vector);
+
+ if (1.0 - BG_FP64_TWO_EPSYLON <= square_module && square_module <= 1.0 + BG_FP64_TWO_EPSYLON) {
+ return 1;
+ }
+
+ if (square_module <= BG_FP64_SQUARE_EPSYLON) {
+ bg_fp64_vector2_reset(vector);
+ return 0;
+ }
+
+ bg_fp64_vector2_divide(vector, sqrt(square_module), vector);
+ return 1;
+}
+
+// =============== Get Normalized =============== //
+
+static inline int bg_fp32_vector2_set_normalized(const BgFP32Vector2* vector, BgFP32Vector2* result)
+{
+ bg_fp32_vector2_copy(vector, result);
+ return bg_fp32_vector2_normalize(result);
+}
+
+static inline int bg_fp64_vector2_set_normalized(const BgFP64Vector2* vector, BgFP64Vector2* result)
+{
+ bg_fp64_vector2_copy(vector, result);
+ return bg_fp64_vector2_normalize(result);
+}
+
+// =================== Angle ==================== //
+
+float bg_fp32_vector2_get_angle(const BgFP32Vector2* vector1, const BgFP32Vector2* vector2, const angle_unit_t unit);
+
+double bg_fp64_vector2_get_angle(const BgFP64Vector2* vector1, const BgFP64Vector2* vector2, const angle_unit_t unit);
+
+// =============== Square Distance ============== //
+
+static inline float bg_fp32_vector2_get_square_distance(const BgFP32Vector2* vector1, const BgFP32Vector2* vector2)
+{
+ const float dx1 = (vector1->x1 - vector2->x1);
+ const float dx2 = (vector1->x2 - vector2->x2);
+
+ return dx1 * dx1 + dx2 * dx2;
+}
+
+static inline double bg_fp64_vector2_get_square_distance(const BgFP64Vector2* vector1, const BgFP64Vector2* vector2)
+{
+ const double dx1 = (vector1->x1 - vector2->x1);
+ const double dx2 = (vector1->x2 - vector2->x2);
+
+ return dx1 * dx1 + dx2 * dx2;
+}
+
+// ================== Distance ================== //
+
+static inline float bg_fp32_vector2_get_distance(const BgFP32Vector2* vector1, const BgFP32Vector2* vector2)
+{
+ return sqrtf(bg_fp32_vector2_get_square_distance(vector1, vector2));
+}
+
+static inline double bg_fp64_vector2_get_distance(const BgFP64Vector2* vector1, const BgFP64Vector2* vector2)
+{
+ return sqrt(bg_fp64_vector2_get_square_distance(vector1, vector2));
+}
+
+// ================== Are Equal ================= //
+
+static inline int bg_fp32_vector2_are_equal(const BgFP32Vector2* vector1, const BgFP32Vector2* vector2)
+{
+ const float square_module1 = bg_fp32_vector2_get_square_module(vector1);
+ const float square_module2 = bg_fp32_vector2_get_square_module(vector2);
+ const float square_module3 = bg_fp32_vector2_get_square_distance(vector1, vector2);
+
+ // 2.0f means dimension amount
+ if (square_module1 < BG_FP32_EPSYLON_EFFECTIVENESS_LIMIT || square_module2 < BG_FP32_EPSYLON_EFFECTIVENESS_LIMIT) {
+ return square_module3 < (2.0f * BG_FP32_SQUARE_EPSYLON);
+ }
+
+ if (square_module1 <= square_module2) {
+ return square_module3 <= (2.0f * BG_FP32_SQUARE_EPSYLON) * square_module2;
+ }
+
+ return square_module3 <= (2.0f * BG_FP32_SQUARE_EPSYLON) * square_module1;
+}
+
+static inline int bg_fp64_vector2_are_equal(const BgFP64Vector2* vector1, const BgFP64Vector2* vector2)
+{
+ const double square_module1 = bg_fp64_vector2_get_square_module(vector1);
+ const double square_module2 = bg_fp64_vector2_get_square_module(vector2);
+ const double square_module3 = bg_fp64_vector2_get_square_distance(vector1, vector2);
+
+ // 2.0 means dimension amount
+ if (square_module1 < BG_FP64_EPSYLON_EFFECTIVENESS_LIMIT || square_module2 < BG_FP64_EPSYLON_EFFECTIVENESS_LIMIT) {
+ return square_module3 < (2.0 * BG_FP64_SQUARE_EPSYLON);
+ }
+
+ if (square_module1 <= square_module2) {
+ return square_module3 <= (2.0 * BG_FP64_SQUARE_EPSYLON) * square_module2;
+ }
+
+ return square_module3 <= (2.0 * BG_FP64_SQUARE_EPSYLON) * square_module1;
+}
+
+#endif
diff --git a/basic-geometry/vector3.c b/basic-geometry/vector3.c
new file mode 100644
index 0000000..cb7450f
--- /dev/null
+++ b/basic-geometry/vector3.c
@@ -0,0 +1,65 @@
+#include "vector3.h"
+
+// =================== Angle ==================== //
+
+float bg_fp32_vector3_get_angle(const BgFP32Vector3* vector1, const BgFP32Vector3* vector2, const angle_unit_t unit)
+{
+ if (vector1 == 0 || vector2 == 0) {
+ return 0.0f;
+ }
+
+ const float square_module1 = bg_fp32_vector3_get_square_module(vector1);
+
+ if (square_module1 <= BG_FP32_SQUARE_EPSYLON) {
+ return 0.0f;
+ }
+
+ const float square_module2 = bg_fp32_vector3_get_square_module(vector2);
+
+ if (square_module2 <= BG_FP32_SQUARE_EPSYLON) {
+ return 0.0f;
+ }
+
+ const float cosine = bg_fp32_vector3_dot_product(vector1, vector2) / sqrtf(square_module1 * square_module2);
+
+ if (cosine >= 1.0f - BG_FP32_EPSYLON) {
+ return 0.0f;
+ }
+
+ if (cosine <= -1.0f + BG_FP32_EPSYLON) {
+ return bg_fp32_angle_get_half_circle(unit);
+ }
+
+ return bg_fp32_radians_to_units(acosf(cosine), unit);
+}
+
+double bg_fp64_vector3_get_angle(const BgFP64Vector3* vector1, const BgFP64Vector3* vector2, const angle_unit_t unit)
+{
+ if (vector1 == 0 || vector2 == 0) {
+ return 0.0;
+ }
+
+ const double square_module1 = bg_fp64_vector3_get_square_module(vector1);
+
+ if (square_module1 <= BG_FP64_SQUARE_EPSYLON) {
+ return 0.0;
+ }
+
+ const double square_module2 = bg_fp64_vector3_get_square_module(vector2);
+
+ if (square_module2 <= BG_FP64_SQUARE_EPSYLON) {
+ return 0.0;
+ }
+
+ const double cosine = bg_fp64_vector3_dot_product(vector1, vector2) / sqrt(square_module1 * square_module2);
+
+ if (cosine >= 1.0 - BG_FP64_EPSYLON) {
+ return 0.0;
+ }
+
+ if (cosine <= -1.0 + BG_FP64_EPSYLON) {
+ return bg_fp64_angle_get_half_circle(unit);
+ }
+
+ return bg_fp64_radians_to_units(acos(cosine), unit);
+}
diff --git a/basic-geometry/vector3.h b/basic-geometry/vector3.h
new file mode 100644
index 0000000..5b91ab0
--- /dev/null
+++ b/basic-geometry/vector3.h
@@ -0,0 +1,475 @@
+#ifndef _GEOMETRY_VECTOR3_H_
+#define _GEOMETRY_VECTOR3_H_
+
+#include "basis.h"
+#include "angle.h"
+
+#include
+
+// ================== Vector3 =================== //
+//
+typedef struct
+{
+ float x1, x2, x3;
+} BgFP32Vector3;
+
+typedef struct
+{
+ double x1, x2, x3;
+} BgFP64Vector3;
+
+// =================== Reset ==================== //
+
+static inline void bg_fp32_vector3_reset(BgFP32Vector3* vector)
+{
+ vector->x1 = 0.0f;
+ vector->x2 = 0.0f;
+ vector->x3 = 0.0f;
+}
+
+static inline void bg_fp64_vector3_reset(BgFP64Vector3* vector)
+{
+ vector->x1 = 0.0;
+ vector->x2 = 0.0;
+ vector->x3 = 0.0;
+}
+
+// ==================== Set ===================== //
+
+static inline void bg_fp32_vector3_set_values(const float x1, const float x2, const float x3, BgFP32Vector3* to)
+{
+ to->x1 = x1;
+ to->x2 = x2;
+ to->x3 = x3;
+}
+
+static inline void bg_fp64_vector3_set_values(const double x1, const double x2, const double x3, BgFP64Vector3* to)
+{
+ to->x1 = x1;
+ to->x2 = x2;
+ to->x3 = x3;
+}
+
+// ==================== Copy ==================== //
+
+static inline void bg_fp32_vector3_copy(const BgFP32Vector3* from, BgFP32Vector3* to)
+{
+ to->x1 = from->x1;
+ to->x2 = from->x2;
+ to->x3 = from->x3;
+}
+
+static inline void bg_fp64_vector3_copy(const BgFP64Vector3* from, BgFP64Vector3* to)
+{
+ to->x1 = from->x1;
+ to->x2 = from->x2;
+ to->x3 = from->x3;
+}
+
+// ============= Copy to twin type ============== //
+
+static inline void bg_fp32_vector3_set_from_fp64(const BgFP64Vector3* from, BgFP32Vector3* to)
+{
+ to->x1 = (float) from->x1;
+ to->x2 = (float) from->x2;
+ to->x3 = (float) from->x3;
+}
+
+static inline void bg_fp64_vector3_set_from_fp32(const BgFP32Vector3* from, BgFP64Vector3* to)
+{
+ to->x1 = from->x1;
+ to->x2 = from->x2;
+ to->x3 = from->x3;
+}
+
+// =================== Reverse ================== //
+
+static inline void bg_fp32_vector3_set_reverse(const BgFP32Vector3* from, BgFP32Vector3* to)
+{
+ to->x1 = -from->x1;
+ to->x2 = -from->x2;
+ to->x3 = -from->x3;
+}
+
+static inline void bg_fp64_vector3_set_reverse(const BgFP64Vector3* from, BgFP64Vector3* to)
+{
+ to->x1 = -from->x1;
+ to->x2 = -from->x2;
+ to->x3 = -from->x3;
+}
+
+// ============= Reverse twin type ============== //
+
+static inline void bg_fp32_vector3_set_reverse_fp64(const BgFP64Vector3* from, BgFP32Vector3* to)
+{
+ to->x1 = (float) -from->x1;
+ to->x2 = (float) -from->x2;
+ to->x3 = (float) -from->x3;
+}
+
+static inline void bg_fp64_vector3_set_reverse_fp32(const BgFP32Vector3* from, BgFP64Vector3* to)
+{
+ to->x1 = -from->x1;
+ to->x2 = -from->x2;
+ to->x3 = -from->x3;
+}
+
+// =================== Module =================== //
+
+static inline float bg_fp32_vector3_get_square_module(const BgFP32Vector3* vector)
+{
+ return vector->x1 * vector->x1 + vector->x2 * vector->x2 + vector->x3 * vector->x3;
+}
+
+static inline double bg_fp64_vector3_get_square_module(const BgFP64Vector3* vector)
+{
+ return vector->x1 * vector->x1 + vector->x2 * vector->x2 + vector->x3 * vector->x3;
+}
+
+static inline float bg_fp32_vector3_get_module(const BgFP32Vector3* vector)
+{
+ return sqrtf(bg_fp32_vector3_get_square_module(vector));
+}
+
+static inline double bg_fp64_vector3_get_module(const BgFP64Vector3* vector)
+{
+ return sqrt(bg_fp64_vector3_get_square_module(vector));
+}
+
+// ================= Comparison ================= //
+
+static inline int bg_fp32_vector3_is_zero(const BgFP32Vector3* vector)
+{
+ return bg_fp32_vector3_get_square_module(vector) <= BG_FP32_SQUARE_EPSYLON;
+}
+
+static inline int bg_fp64_vector3_is_zero(const BgFP64Vector3* vector)
+{
+ return bg_fp64_vector3_get_square_module(vector) <= BG_FP64_SQUARE_EPSYLON;
+}
+
+static inline int bg_fp32_vector3_is_unit(const BgFP32Vector3* vector)
+{
+ const float square_module = bg_fp32_vector3_get_square_module(vector);
+
+ return 1.0f - BG_FP32_TWO_EPSYLON <= square_module && square_module <= 1.0f + BG_FP32_TWO_EPSYLON;
+}
+
+static inline int bg_fp64_vector3_is_unit(const BgFP64Vector3* vector)
+{
+ const double square_module = bg_fp64_vector3_get_square_module(vector);
+
+ return 1.0f - BG_FP64_TWO_EPSYLON <= square_module && square_module <= 1.0f + BG_FP64_TWO_EPSYLON;
+}
+
+// ==================== Add ===================== //
+
+static inline void bg_fp32_vector3_add(const BgFP32Vector3* vector1, const BgFP32Vector3* vector2, BgFP32Vector3* result)
+{
+ result->x1 = vector1->x1 + vector2->x1;
+ result->x2 = vector1->x2 + vector2->x2;
+ result->x3 = vector1->x3 + vector2->x3;
+}
+
+static inline void bg_fp64_vector3_add(const BgFP64Vector3* vector1, const BgFP64Vector3* vector2, BgFP64Vector3* result)
+{
+ result->x1 = vector1->x1 + vector2->x1;
+ result->x2 = vector1->x2 + vector2->x2;
+ result->x3 = vector1->x3 + vector2->x3;
+}
+
+// ================ Subtraction ================= //
+
+static inline void bg_fp32_vector3_subtract(const BgFP32Vector3* minuend, const BgFP32Vector3* subtrahend, BgFP32Vector3* result)
+{
+ result->x1 = minuend->x1 - subtrahend->x1;
+ result->x2 = minuend->x2 - subtrahend->x2;
+ result->x3 = minuend->x3 - subtrahend->x3;
+}
+
+static inline void bg_fp64_vector3_subtract(const BgFP64Vector3* minuend, const BgFP64Vector3* subtrahend, BgFP64Vector3* result)
+{
+ result->x1 = minuend->x1 - subtrahend->x1;
+ result->x2 = minuend->x2 - subtrahend->x2;
+ result->x3 = minuend->x3 - subtrahend->x3;
+}
+
+// =============== Multiplication =============== //
+
+static inline void bg_fp32_vector3_multiply(const BgFP32Vector3* multiplicand, const float multiplier, BgFP32Vector3* result)
+{
+ result->x1 = multiplicand->x1 * multiplier;
+ result->x2 = multiplicand->x2 * multiplier;
+ result->x3 = multiplicand->x3 * multiplier;
+}
+
+static inline void bg_fp64_vector3_multiply(const BgFP64Vector3* multiplicand, const double multiplier, BgFP64Vector3* result)
+{
+ result->x1 = multiplicand->x1 * multiplier;
+ result->x2 = multiplicand->x2 * multiplier;
+ result->x3 = multiplicand->x3 * multiplier;
+}
+
+// ================== Division ================== //
+
+static inline void bg_fp32_vector3_divide(const BgFP32Vector3* dividend, const float divisor, BgFP32Vector3* result)
+{
+ result->x1 = dividend->x1 / divisor;
+ result->x2 = dividend->x2 / divisor;
+ result->x3 = dividend->x3 / divisor;
+}
+
+static inline void bg_fp64_vector3_divide(const BgFP64Vector3* dividend, const double divisor, BgFP64Vector3* result)
+{
+ result->x1 = dividend->x1 / divisor;
+ result->x2 = dividend->x2 / divisor;
+ result->x3 = dividend->x3 / divisor;
+}
+
+// ================ Append scaled =============== //
+
+static inline void bg_fp32_vector3_append_scaled(BgFP32Vector3* basic_vector, const BgFP32Vector3* scalable_vector, const float scale)
+{
+ basic_vector->x1 += scalable_vector->x1 * scale;
+ basic_vector->x2 += scalable_vector->x2 * scale;
+ basic_vector->x3 += scalable_vector->x3 * scale;
+}
+
+static inline void bg_fp64_vector3_append_scaled(BgFP64Vector3* basic_vector, const BgFP64Vector3* scalable_vector, const double scale)
+{
+ basic_vector->x1 += scalable_vector->x1 * scale;
+ basic_vector->x2 += scalable_vector->x2 * scale;
+ basic_vector->x3 += scalable_vector->x3 * scale;
+}
+
+// ================== Average2 ================== //
+
+static inline void bg_fp32_vector3_get_mean2(const BgFP32Vector3* vector1, const BgFP32Vector3* vector2, BgFP32Vector3* result)
+{
+ result->x1 = (vector1->x1 + vector2->x1) * 0.5f;
+ result->x2 = (vector1->x2 + vector2->x2) * 0.5f;
+ result->x3 = (vector1->x3 + vector2->x3) * 0.5f;
+}
+
+static inline void bg_fp64_vector3_get_mean2(const BgFP64Vector3* vector1, const BgFP64Vector3* vector2, BgFP64Vector3* result)
+{
+ result->x1 = (vector1->x1 + vector2->x1) * 0.5;
+ result->x2 = (vector1->x2 + vector2->x2) * 0.5;
+ result->x3 = (vector1->x3 + vector2->x3) * 0.5;
+}
+
+// ================== Average3 ================== //
+
+static inline void bg_fp32_vector3_get_mean3(const BgFP32Vector3* vector1, const BgFP32Vector3* vector2, const BgFP32Vector3* vector3, BgFP32Vector3* result)
+{
+ result->x1 = (vector1->x1 + vector2->x1 + vector3->x1) * BG_FP32_ONE_THIRD;
+ result->x2 = (vector1->x2 + vector2->x2 + vector3->x2) * BG_FP32_ONE_THIRD;
+ result->x3 = (vector1->x3 + vector2->x3 + vector3->x3) * BG_FP32_ONE_THIRD;
+}
+
+static inline void bg_fp64_vector3_get_mean3(const BgFP64Vector3* vector1, const BgFP64Vector3* vector2, const BgFP64Vector3* vector3, BgFP64Vector3* result)
+{
+ result->x1 = (vector1->x1 + vector2->x1 + vector3->x1) * BG_FP64_ONE_THIRD;
+ result->x2 = (vector1->x2 + vector2->x2 + vector3->x2) * BG_FP64_ONE_THIRD;
+ result->x3 = (vector1->x3 + vector2->x3 + vector3->x3) * BG_FP64_ONE_THIRD;
+}
+
+// =============== Scalar Product =============== //
+
+static inline float bg_fp32_vector3_dot_product(const BgFP32Vector3* vector1, const BgFP32Vector3* vector2)
+{
+ return vector1->x1 * vector2->x1 + vector1->x2 * vector2->x2 + vector1->x3 * vector2->x3;
+}
+
+static inline double bg_fp64_vector3_dot_product(const BgFP64Vector3* vector1, const BgFP64Vector3* vector2)
+{
+ return vector1->x1 * vector2->x1 + vector1->x2 * vector2->x2 + vector1->x3 * vector2->x3;
+}
+
+// =============== Triple Product =============== //
+
+static inline float bg_fp32_vector3_triple_product(const BgFP32Vector3* vector1, const BgFP32Vector3* vector2, const BgFP32Vector3* vector3)
+{
+ return vector1->x1 * (vector2->x2 * vector3->x3 - vector2->x3 * vector3->x2)
+ + vector1->x2 * (vector2->x3 * vector3->x1 - vector2->x1 * vector3->x3)
+ + vector1->x3 * (vector2->x1 * vector3->x2 - vector2->x2 * vector3->x1);
+}
+
+static inline double bg_fp64_vector3_triple_product(const BgFP64Vector3* vector1, const BgFP64Vector3* vector2, const BgFP64Vector3* vector3)
+{
+ return vector1->x1 * (vector2->x2 * vector3->x3 - vector2->x3 * vector3->x2)
+ + vector1->x2 * (vector2->x3 * vector3->x1 - vector2->x1 * vector3->x3)
+ + vector1->x3 * (vector2->x1 * vector3->x2 - vector2->x2 * vector3->x1);
+}
+
+// =============== Cross Product ================ //
+
+static inline void bg_fp32_vector3_cross_product(const BgFP32Vector3* vector1, const BgFP32Vector3* vector2, BgFP32Vector3* result)
+{
+ bg_fp32_vector3_set_values(
+ vector1->x2 * vector2->x3 - vector1->x3 * vector2->x2,
+ vector1->x3 * vector2->x1 - vector1->x1 * vector2->x3,
+ vector1->x1 * vector2->x2 - vector1->x2 * vector2->x1,
+ result
+ );
+}
+
+static inline void bg_fp64_vector3_cross_product(const BgFP64Vector3* vector1, const BgFP64Vector3* vector2, BgFP64Vector3* result)
+{
+ bg_fp64_vector3_set_values(
+ vector1->x2 * vector2->x3 - vector1->x3 * vector2->x2,
+ vector1->x3 * vector2->x1 - vector1->x1 * vector2->x3,
+ vector1->x1 * vector2->x2 - vector1->x2 * vector2->x1,
+ result
+ );
+}
+
+// ============ Double Cross Product ============ //
+
+static inline void bg_fp32_vector3_double_cross_product(const BgFP32Vector3* vector1, const BgFP32Vector3* vector2, const BgFP32Vector3* vector3, BgFP32Vector3* result)
+{
+ const float ac = bg_fp32_vector3_dot_product(vector1, vector3);
+ const float ab = bg_fp32_vector3_dot_product(vector1, vector2);
+
+ result->x1 = vector2->x1 * ac - vector3->x1 * ab;
+ result->x2 = vector2->x2 * ac - vector3->x2 * ab;
+ result->x3 = vector2->x3 * ac - vector3->x3 * ab;
+}
+
+static inline void bg_fp64_vector3_double_cross(const BgFP64Vector3* vector1, const BgFP64Vector3* vector2, const BgFP64Vector3* vector3, BgFP64Vector3* result)
+{
+ const double ac = bg_fp64_vector3_dot_product(vector1, vector3);
+ const double ab = bg_fp64_vector3_dot_product(vector1, vector2);
+
+ result->x1 = vector2->x1 * ac - vector3->x1 * ab;
+ result->x2 = vector2->x2 * ac - vector3->x2 * ab;
+ result->x3 = vector2->x3 * ac - vector3->x3 * ab;
+}
+
+// =============== Normalization ================ //
+
+static inline int bg_fp32_vector3_normalize(BgFP32Vector3* vector)
+{
+ const float square_module = bg_fp32_vector3_get_square_module(vector);
+
+ if (1.0f - BG_FP32_TWO_EPSYLON <= square_module && square_module <= 1.0f + BG_FP32_TWO_EPSYLON) {
+ return 1;
+ }
+
+ if (square_module <= BG_FP32_SQUARE_EPSYLON) {
+ bg_fp32_vector3_reset(vector);
+ return 0;
+ }
+
+ bg_fp32_vector3_divide(vector, sqrtf(square_module), vector);
+ return 1;
+}
+
+static inline int bg_fp64_vector3_normalize(BgFP64Vector3* vector)
+{
+ const double square_module = bg_fp64_vector3_get_square_module(vector);
+
+ if (1.0 - BG_FP64_TWO_EPSYLON <= square_module && square_module <= 1.0 + BG_FP64_TWO_EPSYLON) {
+ return 1;
+ }
+
+ if (square_module <= BG_FP64_SQUARE_EPSYLON) {
+ bg_fp64_vector3_reset(vector);
+ return 0;
+ }
+
+ bg_fp64_vector3_divide(vector, sqrt(square_module), vector);
+ return 1;
+}
+
+// =============== Get Normalized =============== //
+
+static inline int bg_fp32_vector3_set_normalized(const BgFP32Vector3* vector, BgFP32Vector3* result)
+{
+ bg_fp32_vector3_copy(vector, result);
+ return bg_fp32_vector3_normalize(result);
+}
+
+static inline int bg_fp64_vector3_set_normalized(const BgFP64Vector3* vector, BgFP64Vector3* result)
+{
+ bg_fp64_vector3_copy(vector, result);
+ return bg_fp64_vector3_normalize(result);
+}
+
+// =================== Angle ==================== //
+
+float bg_fp32_vector3_get_angle(const BgFP32Vector3* vector1, const BgFP32Vector3* vector2, const angle_unit_t unit);
+
+double bg_fp64_vector3_get_angle(const BgFP64Vector3* vector1, const BgFP64Vector3* vector2, const angle_unit_t unit);
+
+// =============== Square Distance ============== //
+
+static inline float bg_fp32_vector3_get_square_distance(const BgFP32Vector3* vector1, const BgFP32Vector3* vector2)
+{
+ const float dx1 = (vector1->x1 - vector2->x1);
+ const float dx2 = (vector1->x2 - vector2->x2);
+ const float dx3 = (vector1->x3 - vector2->x3);
+
+ return dx1 * dx1 + dx2 * dx2 + dx3 * dx3;
+}
+
+static inline double bg_fp64_vector3_get_square_distance(const BgFP64Vector3* vector1, const BgFP64Vector3* vector2)
+{
+ const double dx1 = (vector1->x1 - vector2->x1);
+ const double dx2 = (vector1->x2 - vector2->x2);
+ const double dx3 = (vector1->x3 - vector2->x3);
+
+ return dx1 * dx1 + dx2 * dx2 + dx3 * dx3;
+}
+
+// ================== Distance ================== //
+
+static inline float bg_fp32_vector3_get_distance(const BgFP32Vector3* vector1, const BgFP32Vector3* vector2)
+{
+ return sqrtf(bg_fp32_vector3_get_square_distance(vector1, vector2));
+}
+
+static inline double bg_fp64_vector3_get_distance(const BgFP64Vector3* vector1, const BgFP64Vector3* vector2)
+{
+ return sqrt(bg_fp64_vector3_get_square_distance(vector1, vector2));
+}
+
+// ================== Are Equal ================= //
+
+static inline int bg_fp32_vector3_are_equal(const BgFP32Vector3* vector1, const BgFP32Vector3* vector2)
+{
+ const float square_module1 = bg_fp32_vector3_get_square_module(vector1);
+ const float square_module2 = bg_fp32_vector3_get_square_module(vector2);
+ const float square_module3 = bg_fp32_vector3_get_square_distance(vector1, vector2);
+
+ // 3.0f means dimension amount
+ if (square_module1 < BG_FP32_EPSYLON_EFFECTIVENESS_LIMIT || square_module2 < BG_FP32_EPSYLON_EFFECTIVENESS_LIMIT) {
+ return square_module3 < (3.0f * BG_FP32_SQUARE_EPSYLON);
+ }
+
+ if (square_module1 <= square_module2) {
+ return square_module3 <= (3.0f * BG_FP32_SQUARE_EPSYLON) * square_module2;
+ }
+
+ return square_module3 <= (3.0f * BG_FP32_SQUARE_EPSYLON) * square_module1;
+}
+
+static inline int bg_fp64_vector3_are_equal(const BgFP64Vector3* vector1, const BgFP64Vector3* vector2)
+{
+ const double square_module1 = bg_fp64_vector3_get_square_module(vector1);
+ const double square_module2 = bg_fp64_vector3_get_square_module(vector2);
+ const double square_module3 = bg_fp64_vector3_get_square_distance(vector1, vector2);
+
+ // 3.0 means dimension amount
+ if (square_module1 < BG_FP64_EPSYLON_EFFECTIVENESS_LIMIT || square_module2 < BG_FP64_EPSYLON_EFFECTIVENESS_LIMIT) {
+ return square_module3 < (3.0 * BG_FP64_SQUARE_EPSYLON);
+ }
+
+ if (square_module1 <= square_module2) {
+ return square_module3 <= (3.0 * BG_FP64_SQUARE_EPSYLON) * square_module2;
+ }
+
+ return square_module3 <= (3.0 * BG_FP64_SQUARE_EPSYLON) * square_module1;
+}
+
+#endif
diff --git a/basic-geometry/versor.c b/basic-geometry/versor.c
new file mode 100644
index 0000000..f9242b0
--- /dev/null
+++ b/basic-geometry/versor.c
@@ -0,0 +1,138 @@
+#include
+
+#include "angle.h"
+#include "versor.h"
+
+const BgFP32Versor BG_FP32_IDLE_VERSOR = { 1.0f, 0.0f, 0.0f, 0.0f };
+
+const BgFP64Versor BG_FP64_IDLE_VERSOR = { 1.0, 0.0, 0.0, 0.0 };
+
+void __bg_fp32_versor_normalize(const float square_module, __BgFP32DarkTwinVersor* twin)
+{
+ if (square_module <= BG_FP32_SQUARE_EPSYLON || (twin->s0 * twin->s0) >= (1.0f - BG_FP32_TWO_EPSYLON) * square_module) {
+ twin->s0 = 1.0f;
+ twin->x1 = 0.0f;
+ twin->x2 = 0.0f;
+ twin->x3 = 0.0f;
+ return;
+ }
+
+ const float module = sqrtf(square_module);
+
+ twin->s0 /= module;
+ twin->x1 /= module;
+ twin->x2 /= module;
+ twin->x3 /= module;
+}
+
+void __bg_fp64_versor_normalize(const double square_module, __BgFP64DarkTwinVersor* twin)
+{
+ if (square_module <= BG_FP64_SQUARE_EPSYLON || (twin->s0 * twin->s0) >= (1.0 - BG_FP64_TWO_EPSYLON) * square_module) {
+ twin->s0 = 1.0;
+ twin->x1 = 0.0;
+ twin->x2 = 0.0;
+ twin->x3 = 0.0;
+ return;
+ }
+
+ const double module = sqrt(square_module);
+
+ twin->s0 /= module;
+ twin->x1 /= module;
+ twin->x2 /= module;
+ twin->x3 /= module;
+}
+
+// =============== Set Crude Turn =============== //
+
+void bg_fp32_versor_set_crude_turn(const float x1, const float x2, const float x3, const float angle, const angle_unit_t unit, BgFP32Versor* result)
+{
+ const float square_vector = x1 * x1 + x2 * x2 + x3 * x3;
+
+ if (square_vector <= BG_FP32_SQUARE_EPSYLON) {
+ bg_fp32_versor_reset(result);
+ return;
+ }
+
+ const float half_angle = bg_fp32_angle_to_radians(0.5f * angle, unit);
+
+ const float sine = sinf(half_angle);
+
+ if (-BG_FP32_EPSYLON <= sine && sine <= BG_FP32_EPSYLON) {
+ bg_fp32_versor_reset(result);
+ return;
+ }
+
+ const float multiplier = sine / sqrtf(square_vector);
+
+ bg_fp32_versor_set_values(cosf(half_angle), x1 * multiplier, x2 * multiplier, x3 * multiplier, result);
+}
+
+void bg_fp64_versor_set_crude_turn(const double x1, const double x2, const double x3, const double angle, const angle_unit_t unit, BgFP64Versor* result)
+{
+ const double square_vector = x1 * x1 + x2 * x2 + x3 * x3;
+
+ if (square_vector <= BG_FP64_SQUARE_EPSYLON) {
+ bg_fp64_versor_reset(result);
+ return;
+ }
+
+ const double half_angle = bg_fp64_angle_to_radians(0.5 * angle, unit);
+
+ const double sine = sin(half_angle);
+
+ if (-BG_FP64_EPSYLON <= sine && sine <= BG_FP64_EPSYLON) {
+ bg_fp64_versor_reset(result);
+ return;
+ }
+
+ const double multiplier = sine / sqrt(square_vector);
+
+ bg_fp64_versor_set_values(cos(half_angle), x1 * multiplier, x2 * multiplier, x3 * multiplier, result);
+}
+
+// ================= Rotation3 ================== //
+
+void bg_fp32_versor_get_rotation(const BgFP32Versor* versor, BgFP32Rotation3* result)
+{
+ if (versor == 0 || result == 0) {
+ return;
+ }
+
+ if (versor->s0 <= -(1.0f - BG_FP32_EPSYLON) || 1.0f - BG_FP32_EPSYLON <= versor->s0) {
+ bg_fp32_rotation_reset(result);
+ return;
+ }
+
+ const float square_vector = versor->x1 * versor->x1 + versor->x2 * versor->x2 + versor->x3 * versor->x3;
+
+ result->radians = 2.0f * acosf(versor->s0 / sqrtf(versor->s0 * versor->s0 + square_vector));
+
+ const float vector_module = sqrtf(square_vector);
+
+ result->axis.x1 = versor->x1 / vector_module;
+ result->axis.x2 = versor->x2 / vector_module;
+ result->axis.x3 = versor->x3 / vector_module;
+}
+
+void bg_fp64_versor_get_rotation(const BgFP64Versor* versor, BgFP64Rotation3* result)
+{
+ if (versor == 0 || result == 0) {
+ return;
+ }
+
+ if (versor->s0 <= -(1.0 - BG_FP64_EPSYLON) || 1.0 - BG_FP64_EPSYLON <= versor->s0) {
+ bg_fp64_rotation_reset(result);
+ return;
+ }
+
+ const double square_vector = versor->x1 * versor->x1 + versor->x2 * versor->x2 + versor->x3 * versor->x3;
+
+ result->radians = 2.0 * acos(versor->s0 / sqrt(versor->s0 * versor->s0 + square_vector));
+
+ const double vector_module = sqrt(square_vector);
+
+ result->axis.x1 = versor->x1 / vector_module;
+ result->axis.x2 = versor->x2 / vector_module;
+ result->axis.x3 = versor->x3 / vector_module;
+}
diff --git a/basic-geometry/versor.h b/basic-geometry/versor.h
new file mode 100644
index 0000000..03d397a
--- /dev/null
+++ b/basic-geometry/versor.h
@@ -0,0 +1,632 @@
+#ifndef _GEOMETRY_VERSOR_H_
+#define _GEOMETRY_VERSOR_H_
+
+#include
+
+#include "basis.h"
+#include "vector3.h"
+#include "rotation3.h"
+#include "matrix3x3.h"
+
+// =================== Types ==================== //
+
+typedef struct {
+ const float s0, x1, x2, x3;
+} BgFP32Versor;
+
+typedef struct {
+ const double s0, x1, x2, x3;
+} BgFP64Versor;
+
+// ================= Dark Twins ================= //
+
+typedef struct {
+ float s0, x1, x2, x3;
+} __BgFP32DarkTwinVersor;
+
+typedef struct {
+ double s0, x1, x2, x3;
+} __BgFP64DarkTwinVersor;
+
+// ================= Constants ================== //
+
+extern const BgFP32Versor BG_FP32_IDLE_VERSOR;
+extern const BgFP64Versor BG_FP64_IDLE_VERSOR;
+
+// =================== Reset ==================== //
+
+static inline void bg_fp32_versor_reset(BgFP32Versor* versor)
+{
+ __BgFP32DarkTwinVersor* twin = (__BgFP32DarkTwinVersor*)versor;
+
+ twin->s0 = 1.0f;
+ twin->x1 = 0.0f;
+ twin->x2 = 0.0f;
+ twin->x3 = 0.0f;
+}
+
+static inline void bg_fp64_versor_reset(BgFP64Versor* versor)
+{
+ __BgFP64DarkTwinVersor* twin = (__BgFP64DarkTwinVersor*)versor;
+
+ twin->s0 = 1.0;
+ twin->x1 = 0.0;
+ twin->x2 = 0.0;
+ twin->x3 = 0.0;
+}
+
+// ==================== Set ===================== //
+
+void __bg_fp32_versor_normalize(const float square_module, __BgFP32DarkTwinVersor* twin);
+
+void __bg_fp64_versor_normalize(const double square_module, __BgFP64DarkTwinVersor* twin);
+
+static inline void bg_fp32_versor_set_values(const float s0, const float x1, const float x2, const float x3, BgFP32Versor* versor)
+{
+ __BgFP32DarkTwinVersor* twin = (__BgFP32DarkTwinVersor*)versor;
+
+ twin->s0 = s0;
+ twin->x1 = x1;
+ twin->x2 = x2;
+ twin->x3 = x3;
+
+ const float square_module = (s0 * s0 + x1 * x1) + (x2 * x2 + x3 * x3);
+
+ if (1.0f - BG_FP32_TWO_EPSYLON <= square_module && square_module <= 1.0f + BG_FP32_TWO_EPSYLON) {
+ return;
+ }
+
+ __bg_fp32_versor_normalize(square_module, (__BgFP32DarkTwinVersor*)versor);
+}
+
+static inline void bg_fp64_versor_set_values(const double s0, const double x1, const double x2, const double x3, BgFP64Versor* versor)
+{
+ __BgFP64DarkTwinVersor* twin = (__BgFP64DarkTwinVersor*)versor;
+
+ twin->s0 = s0;
+ twin->x1 = x1;
+ twin->x2 = x2;
+ twin->x3 = x3;
+
+ const double square_module = (s0 * s0 + x1 * x1) + (x2 * x2 + x3 * x3);
+
+ if (1.0 - BG_FP64_TWO_EPSYLON <= square_module && square_module <= 1.0 + BG_FP64_TWO_EPSYLON) {
+ return;
+ }
+
+ __bg_fp64_versor_normalize(square_module, twin);
+}
+
+// ==================== Copy ==================== //
+
+static inline void bg_fp32_versor_copy(const BgFP32Versor* from, BgFP32Versor* to)
+{
+ __BgFP32DarkTwinVersor* twin = (__BgFP32DarkTwinVersor*)to;
+
+ twin->s0 = from->s0;
+ twin->x1 = from->x1;
+ twin->x2 = from->x2;
+ twin->x3 = from->x3;
+}
+
+static inline void bg_fp64_versor_copy(const BgFP64Versor* from, BgFP64Versor* to)
+{
+ __BgFP64DarkTwinVersor* twin = (__BgFP64DarkTwinVersor*)to;
+
+ twin->s0 = from->s0;
+ twin->x1 = from->x1;
+ twin->x2 = from->x2;
+ twin->x3 = from->x3;
+}
+
+// =============== Set Crude Turn =============== //
+
+void bg_fp32_versor_set_crude_turn(const float x1, const float x2, const float x3, const float angle, const angle_unit_t unit, BgFP32Versor* result);
+
+void bg_fp64_versor_set_crude_turn(const double x1, const double x2, const double x3, const double angle, const angle_unit_t unit, BgFP64Versor* result);
+
+// ================== Set Turn ================== //
+
+static inline void bg_fp32_versor_set_turn(const BgFP32Vector3* axis, const float angle, const angle_unit_t unit, BgFP32Versor* result)
+{
+ bg_fp32_versor_set_crude_turn(axis->x1, axis->x2, axis->x3, angle, unit, result);
+}
+
+static inline void bg_fp64_versor_set_turn(const BgFP32Vector3* axis, const double angle, const angle_unit_t unit, BgFP64Versor* result)
+{
+ bg_fp64_versor_set_crude_turn(axis->x1, axis->x2, axis->x3, angle, unit, result);
+}
+
+// ================ Set Rotation ================ //
+
+static inline void bg_fp32_versor_set_rotation(const BgFP32Rotation3* rotation, BgFP32Versor* result)
+{
+ bg_fp32_versor_set_crude_turn(rotation->axis.x1, rotation->axis.x2, rotation->axis.x3, rotation->radians, BG_ANGLE_UNIT_RADIANS, result);
+}
+
+static inline void bg_fp64_versor_set_rotation(const BgFP64Rotation3* rotation, BgFP64Versor* result)
+{
+ bg_fp64_versor_set_crude_turn(rotation->axis.x1, rotation->axis.x2, rotation->axis.x3, rotation->radians, BG_ANGLE_UNIT_RADIANS, result);
+}
+
+// ================= Comparison ================= //
+
+static inline int bg_fp32_versor_is_idle(const BgFP32Versor* versor)
+{
+ return 1.0f - BG_FP32_EPSYLON <= versor->s0 || versor->s0 <= -(1.0 - BG_FP32_EPSYLON);
+}
+
+static inline int bg_fp64_versor_is_idle(const BgFP64Versor* versor)
+{
+ return 1.0 - BG_FP64_EPSYLON <= versor->s0 || versor->s0 <= -(1.0 - BG_FP64_EPSYLON);
+}
+
+// ============= Copy to twin type ============== //
+
+static inline void bg_fp32_versor_set_from_fp64(const BgFP64Versor* versor, BgFP32Versor* result)
+{
+ bg_fp32_versor_set_values(
+ (float) versor->s0,
+ (float) versor->x1,
+ (float) versor->x2,
+ (float) versor->x3,
+ result
+ );
+}
+
+static inline void bg_fp64_versor_set_from_fp32(const BgFP32Versor* versor, BgFP64Versor* result)
+{
+ bg_fp64_versor_set_values(
+ versor->s0,
+ versor->x1,
+ versor->x2,
+ versor->x3,
+ result
+ );
+}
+
+// ================= Inversion ================== //
+
+static inline void bg_fp32_versor_invert(BgFP32Versor* versor)
+{
+ __BgFP32DarkTwinVersor* twin = (__BgFP32DarkTwinVersor*)versor;
+ twin->x1 = -versor->x1;
+ twin->x2 = -versor->x2;
+ twin->x3 = -versor->x3;
+}
+
+static inline void bg_fp64_versor_invert(BgFP64Versor* versor)
+{
+ __BgFP64DarkTwinVersor* twin = (__BgFP64DarkTwinVersor*)versor;
+ twin->x1 = -versor->x1;
+ twin->x2 = -versor->x2;
+ twin->x3 = -versor->x3;
+}
+
+// ================ Set Inverted ================ //
+
+static inline void bg_fp32_versor_set_inverted(const BgFP32Versor* versor, BgFP32Versor* to)
+{
+ __BgFP32DarkTwinVersor* twin = (__BgFP32DarkTwinVersor*)to;
+ twin->s0 = versor->s0;
+ twin->x1 = -versor->x1;
+ twin->x2 = -versor->x2;
+ twin->x3 = -versor->x3;
+}
+
+static inline void bg_fp64_versor_set_inverted(const BgFP64Versor* versor, BgFP64Versor* to)
+{
+ __BgFP64DarkTwinVersor* twin = (__BgFP64DarkTwinVersor*)to;
+ twin->s0 = versor->s0;
+ twin->x1 = -versor->x1;
+ twin->x2 = -versor->x2;
+ twin->x3 = -versor->x3;
+}
+
+// ================ Set Inverted ================ //
+
+static inline void bg_fp32_versor_set_inverted_fp64(const BgFP64Versor* versor, BgFP32Versor* to)
+{
+ bg_fp32_versor_set_values(
+ (float) versor->s0,
+ (float) -versor->x1,
+ (float) -versor->x2,
+ (float) -versor->x3,
+ to
+ );
+}
+
+static inline void bg_fp64_versor_set_inverted_fp32(const BgFP32Versor* versor, BgFP64Versor* to)
+{
+ bg_fp64_versor_set_values(
+ versor->s0,
+ -versor->x1,
+ -versor->x2,
+ -versor->x3,
+ to
+ );
+}
+
+// ================ Combination ================= //
+
+static inline void bg_fp32_versor_combine(const BgFP32Versor* second, const BgFP32Versor* first, BgFP32Versor* result)
+{
+ const float s0 = (second->s0 * first->s0 - second->x1 * first->x1) - (second->x2 * first->x2 + second->x3 * first->x3);
+ const float x1 = (second->x1 * first->s0 + second->s0 * first->x1) - (second->x3 * first->x2 - second->x2 * first->x3);
+ const float x2 = (second->x2 * first->s0 + second->s0 * first->x2) - (second->x1 * first->x3 - second->x3 * first->x1);
+ const float x3 = (second->x3 * first->s0 + second->s0 * first->x3) - (second->x2 * first->x1 - second->x1 * first->x2);
+
+ const float square_module = (s0 * s0 + x1 * x1) + (x2 * x2 + x3 * x3);
+
+ __BgFP32DarkTwinVersor* twin = (__BgFP32DarkTwinVersor*)result;
+
+ twin->s0 = s0;
+ twin->x1 = x1;
+ twin->x2 = x2;
+ twin->x3 = x3;
+
+ if (1.0f - BG_FP32_TWO_EPSYLON <= square_module && square_module <= 1.0f + BG_FP32_TWO_EPSYLON) {
+ return;
+ }
+
+ __bg_fp32_versor_normalize(square_module, twin);
+}
+
+static inline void bg_fp64_versor_combine(const BgFP64Versor* second, const BgFP64Versor* first, BgFP64Versor* result)
+{
+ const double s0 = (second->s0 * first->s0 - second->x1 * first->x1) - (second->x2 * first->x2 + second->x3 * first->x3);
+ const double x1 = (second->x1 * first->s0 + second->s0 * first->x1) - (second->x3 * first->x2 - second->x2 * first->x3);
+ const double x2 = (second->x2 * first->s0 + second->s0 * first->x2) - (second->x1 * first->x3 - second->x3 * first->x1);
+ const double x3 = (second->x3 * first->s0 + second->s0 * first->x3) - (second->x2 * first->x1 - second->x1 * first->x2);
+
+ const double square_module = (s0 * s0 + x1 * x1) + (x2 * x2 + x3 * x3);
+
+ __BgFP64DarkTwinVersor* twin = (__BgFP64DarkTwinVersor*)result;
+
+ twin->s0 = s0;
+ twin->x1 = x1;
+ twin->x2 = x2;
+ twin->x3 = x3;
+
+ if (1.0 - BG_FP64_TWO_EPSYLON <= square_module && square_module <= 1.0 + BG_FP64_TWO_EPSYLON) {
+ return;
+ }
+
+ __bg_fp64_versor_normalize(square_module, twin);
+}
+
+// ================= Rotation3 ================== //
+
+void bg_fp32_versor_get_rotation(const BgFP32Versor* versor, BgFP32Rotation3* result);
+
+void bg_fp64_versor_get_rotation(const BgFP64Versor* versor, BgFP64Rotation3* result);
+
+// =========== Make Rotation Matrix3x3 ========== //
+
+static inline void bg_fp32_versor_get_rotation_matrix(const BgFP32Versor* versor, BgFP32Matrix3x3* matrix)
+{
+ 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 s0x1 = 2.0f * versor->s0 * versor->x1;
+ const float s0x2 = 2.0f * versor->s0 * versor->x2;
+ const float s0x3 = 2.0f * versor->s0 * versor->x3;
+
+ const float x1x2 = 2.0f * versor->x1 * versor->x2;
+ const float x1x3 = 2.0f * versor->x1 * versor->x3;
+ const float x2x3 = 2.0f * versor->x2 * versor->x3;
+
+ matrix->r1c1 = (s0s0 + x1x1) - (x2x2 + x3x3);
+ matrix->r2c2 = (s0s0 + x2x2) - (x1x1 + x3x3);
+ matrix->r3c3 = (s0s0 + x3x3) - (x1x1 + x2x2);
+
+ matrix->r1c2 = x1x2 - s0x3;
+ matrix->r2c3 = x2x3 - s0x1;
+ matrix->r3c1 = x1x3 - s0x2;
+
+ matrix->r2c1 = x1x2 + s0x3;
+ matrix->r3c2 = x2x3 + s0x1;
+ matrix->r1c3 = x1x3 + s0x2;
+}
+
+static inline void bg_fp64_versor_get_rotation_matrix(const BgFP64Versor* versor, BgFP64Matrix3x3* matrix)
+{
+ 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 s0x1 = 2.0 * versor->s0 * versor->x1;
+ const double s0x2 = 2.0 * versor->s0 * versor->x2;
+ const double s0x3 = 2.0 * versor->s0 * versor->x3;
+
+ const double x1x2 = 2.0 * versor->x1 * versor->x2;
+ const double x1x3 = 2.0 * versor->x1 * versor->x3;
+ const double x2x3 = 2.0 * versor->x2 * versor->x3;
+
+ matrix->r1c1 = (s0s0 + x1x1) - (x2x2 + x3x3);
+ matrix->r2c2 = (s0s0 + x2x2) - (x1x1 + x3x3);
+ matrix->r3c3 = (s0s0 + x3x3) - (x1x1 + x2x2);
+
+ matrix->r1c2 = x1x2 - s0x3;
+ matrix->r2c3 = x2x3 - s0x1;
+ matrix->r3c1 = x1x3 - s0x2;
+
+ matrix->r2c1 = x1x2 + s0x3;
+ matrix->r3c2 = x2x3 + s0x1;
+ matrix->r1c3 = x1x3 + s0x2;
+}
+
+// =========== Make Reverse Matrix3x3 =========== //
+
+static inline void bg_fp32_versor_get_reverse_matrix(const BgFP32Versor* versor, BgFP32Matrix3x3* matrix)
+{
+ 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 s0x1 = 2.0f * versor->s0 * versor->x1;
+ const float s0x2 = 2.0f * versor->s0 * versor->x2;
+ const float s0x3 = 2.0f * versor->s0 * versor->x3;
+
+ const float x1x2 = 2.0f * versor->x1 * versor->x2;
+ const float x1x3 = 2.0f * versor->x1 * versor->x3;
+ const float x2x3 = 2.0f * versor->x2 * versor->x3;
+
+ matrix->r1c1 = (s0s0 + x1x1) - (x2x2 + x3x3);
+ matrix->r2c2 = (s0s0 + x2x2) - (x1x1 + x3x3);
+ matrix->r3c3 = (s0s0 + x3x3) - (x1x1 + x2x2);
+
+ matrix->r1c2 = x1x2 + s0x3;
+ matrix->r2c3 = x2x3 + s0x1;
+ matrix->r3c1 = x1x3 + s0x2;
+
+ matrix->r2c1 = x1x2 - s0x3;
+ matrix->r3c2 = x2x3 - s0x1;
+ matrix->r1c3 = x1x3 - s0x2;
+}
+
+static inline void bg_fp64_versor_get_reverse_matrix(const BgFP64Versor* versor, BgFP64Matrix3x3* matrix)
+{
+ 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 s0x1 = 2.0 * versor->s0 * versor->x1;
+ const double s0x2 = 2.0 * versor->s0 * versor->x2;
+ const double s0x3 = 2.0 * versor->s0 * versor->x3;
+
+ const double x1x2 = 2.0 * versor->x1 * versor->x2;
+ const double x1x3 = 2.0 * versor->x1 * versor->x3;
+ const double x2x3 = 2.0 * versor->x2 * versor->x3;
+
+ matrix->r1c1 = (s0s0 + x1x1) - (x2x2 + x3x3);
+ matrix->r2c2 = (s0s0 + x2x2) - (x1x1 + x3x3);
+ matrix->r3c3 = (s0s0 + x3x3) - (x1x1 + x2x2);
+
+ matrix->r1c2 = x1x2 + s0x3;
+ matrix->r2c3 = x2x3 + s0x1;
+ matrix->r3c1 = x1x3 + s0x2;
+
+ matrix->r2c1 = x1x2 - s0x3;
+ matrix->r3c2 = x2x3 - s0x1;
+ matrix->r1c3 = x1x3 - s0x2;
+}
+
+// ================ Turn Vector ================= //
+
+static inline void bg_fp32_versor_turn(const BgFP32Versor* versor, const BgFP32Vector3* vector, BgFP32Vector3* result)
+{
+ const float tx1 = 2.0f * (versor->x2 * vector->x3 - versor->x3 * vector->x2);
+ const float tx2 = 2.0f * (versor->x3 * vector->x1 - versor->x1 * vector->x3);
+ const float tx3 = 2.0f * (versor->x1 * vector->x2 - versor->x2 * vector->x1);
+
+ const float x1 = (vector->x1 + tx1 * versor->s0) + (versor->x2 * tx3 - versor->x3 * tx2);
+ const float x2 = (vector->x2 + tx2 * versor->s0) + (versor->x3 * tx1 - versor->x1 * tx3);
+ const float x3 = (vector->x3 + tx3 * versor->s0) + (versor->x1 * tx2 - versor->x2 * tx1);
+
+ result->x1 = x1;
+ result->x2 = x2;
+ result->x3 = x3;
+}
+
+static inline void bg_fp64_versor_turn(const BgFP64Versor* versor, const BgFP64Vector3* vector, BgFP64Vector3* result)
+{
+ const double tx1 = 2.0 * (versor->x2 * vector->x3 - versor->x3 * vector->x2);
+ const double tx2 = 2.0 * (versor->x3 * vector->x1 - versor->x1 * vector->x3);
+ const double tx3 = 2.0 * (versor->x1 * vector->x2 - versor->x2 * vector->x1);
+
+ const double x1 = (vector->x1 + tx1 * versor->s0) + (versor->x2 * tx3 - versor->x3 * tx2);
+ const double x2 = (vector->x2 + tx2 * versor->s0) + (versor->x3 * tx1 - versor->x1 * tx3);
+ const double x3 = (vector->x3 + tx3 * versor->s0) + (versor->x1 * tx2 - versor->x2 * tx1);
+
+ result->x1 = x1;
+ result->x2 = x2;
+ result->x3 = x3;
+}
+
+// ================ Turn2 Vector ================ //
+
+static inline void bg_fp32_versor_turn2(const BgFP32Versor* versor, const BgFP32Vector3* vector, BgFP32Vector3* result)
+{
+ 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 s0x1 = 2.0f * versor->s0 * versor->x1;
+ const float s0x2 = 2.0f * versor->s0 * versor->x2;
+ const float s0x3 = 2.0f * versor->s0 * versor->x3;
+
+ const float x1x2 = 2.0f * versor->x1 * versor->x2;
+ const float x1x3 = 2.0f * versor->x1 * versor->x3;
+ const float x2x3 = 2.0f * versor->x2 * versor->x3;
+
+ const float r2c1 = x1x2 + s0x3;
+ const float r3c2 = x2x3 + s0x1;
+ const float r1c3 = x1x3 + s0x2;
+
+ const float r1c1 = (s0s0 + x1x1) - (x2x2 + x3x3);
+ const float r2c2 = (s0s0 + x2x2) - (x1x1 + x3x3);
+ const float r3c3 = (s0s0 + x3x3) - (x1x1 + x2x2);
+
+ const float r1c2 = x1x2 - s0x3;
+ const float r2c3 = x2x3 - s0x1;
+ const float r3c1 = x1x3 - s0x2;
+
+ const float x1 = r1c1 * vector->x1 + r1c2 * vector->x2 + r1c3 * vector->x3;
+ const float x2 = r2c1 * vector->x1 + r2c2 * vector->x2 + r2c3 * vector->x3;
+ const float x3 = r3c1 * vector->x1 + r3c2 * vector->x2 + r3c3 * vector->x3;
+
+ result->x1 = x1;
+ result->x2 = x2;
+ result->x3 = x3;
+}
+
+static inline void bg_fp64_versor_turn2(const BgFP64Versor* versor, const BgFP64Vector3* vector, BgFP64Vector3* result)
+{
+ 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 s0x1 = 2.0f * versor->s0 * versor->x1;
+ const double s0x2 = 2.0f * versor->s0 * versor->x2;
+ const double s0x3 = 2.0f * versor->s0 * versor->x3;
+
+ const double x1x2 = 2.0f * versor->x1 * versor->x2;
+ const double x1x3 = 2.0f * versor->x1 * versor->x3;
+ const double x2x3 = 2.0f * versor->x2 * versor->x3;
+
+ const double r2c1 = x1x2 + s0x3;
+ const double r3c2 = x2x3 + s0x1;
+ const double r1c3 = x1x3 + s0x2;
+
+ const double r1c1 = (s0s0 + x1x1) - (x2x2 + x3x3);
+ const double r2c2 = (s0s0 + x2x2) - (x1x1 + x3x3);
+ const double r3c3 = (s0s0 + x3x3) - (x1x1 + x2x2);
+
+ const double r1c2 = x1x2 - s0x3;
+ const double r2c3 = x2x3 - s0x1;
+ const double r3c1 = x1x3 - s0x2;
+
+ const double x1 = r1c1 * vector->x1 + r1c2 * vector->x2 + r1c3 * vector->x3;
+ const double x2 = r2c1 * vector->x1 + r2c2 * vector->x2 + r2c3 * vector->x3;
+ const double x3 = r3c1 * vector->x1 + r3c2 * vector->x2 + r3c3 * vector->x3;
+
+ result->x1 = x1;
+ result->x2 = x2;
+ result->x3 = x3;
+}
+
+// ============== Turn Vector Back ============== //
+
+static inline void bg_fp32_versor_turn_back(const BgFP32Versor* versor, const BgFP32Vector3* vector, BgFP32Vector3* result)
+{
+ const float tx1 = 2.0f * (versor->x2 * vector->x3 - versor->x3 * vector->x2);
+ const float tx2 = 2.0f * (versor->x3 * vector->x1 - versor->x1 * vector->x3);
+ const float tx3 = 2.0f * (versor->x1 * vector->x2 - versor->x2 * vector->x1);
+
+ const float x1 = (vector->x1 - tx1 * versor->s0) + (versor->x2 * tx3 - versor->x3 * tx2);
+ const float x2 = (vector->x2 - tx2 * versor->s0) + (versor->x3 * tx1 - versor->x1 * tx3);
+ const float x3 = (vector->x3 - tx3 * versor->s0) + (versor->x1 * tx2 - versor->x2 * tx1);
+
+ result->x1 = x1;
+ result->x2 = x2;
+ result->x3 = x3;
+}
+
+static inline void bg_fp64_versor_turn_back(const BgFP64Versor* versor, const BgFP64Vector3* vector, BgFP64Vector3* result)
+{
+ const double tx1 = 2.0 * (versor->x2 * vector->x3 - versor->x3 * vector->x2);
+ const double tx2 = 2.0 * (versor->x3 * vector->x1 - versor->x1 * vector->x3);
+ const double tx3 = 2.0 * (versor->x1 * vector->x2 - versor->x2 * vector->x1);
+
+ const double x1 = (vector->x1 - tx1 * versor->s0) + (versor->x2 * tx3 - versor->x3 * tx2);
+ const double x2 = (vector->x2 - tx2 * versor->s0) + (versor->x3 * tx1 - versor->x1 * tx3);
+ const double x3 = (vector->x3 - tx3 * versor->s0) + (versor->x1 * tx2 - versor->x2 * tx1);
+
+ result->x1 = x1;
+ result->x2 = x2;
+ result->x3 = x3;
+}
+
+// ============== Turn Vector Back2 ============= //
+
+static inline void bg_fp32_versor_turn_back2(const BgFP32Versor* versor, const BgFP32Vector3* vector, BgFP32Vector3* result)
+{
+ 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 s0x1 = 2.0f * versor->s0 * versor->x1;
+ const float s0x2 = 2.0f * versor->s0 * versor->x2;
+ const float s0x3 = 2.0f * versor->s0 * versor->x3;
+
+ const float x1x2 = 2.0f * versor->x1 * versor->x2;
+ const float x1x3 = 2.0f * versor->x1 * versor->x3;
+ const float x2x3 = 2.0f * versor->x2 * versor->x3;
+
+ const float r1c2 = x1x2 + s0x3;
+ const float r2c3 = x2x3 + s0x1;
+ const float r3c1 = x1x3 + s0x2;
+
+ const float r1c1 = (s0s0 + x1x1) - (x2x2 + x3x3);
+ const float r2c2 = (s0s0 + x2x2) - (x1x1 + x3x3);
+ const float r3c3 = (s0s0 + x3x3) - (x1x1 + x2x2);
+
+ const float r2c1 = x1x2 - s0x3;
+ const float r3c2 = x2x3 - s0x1;
+ const float r1c3 = x1x3 - s0x2;
+
+ const float x1 = r1c1 * vector->x1 + r1c2 * vector->x2 + r1c3 * vector->x3;
+ const float x2 = r2c1 * vector->x1 + r2c2 * vector->x2 + r2c3 * vector->x3;
+ const float x3 = r3c1 * vector->x1 + r3c2 * vector->x2 + r3c3 * vector->x3;
+
+ result->x1 = x1;
+ result->x2 = x2;
+ result->x3 = x3;
+}
+
+static inline void bg_fp64_versor_turn_back2(const BgFP64Versor* versor, const BgFP64Vector3* vector, BgFP64Vector3* result)
+{
+ 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 s0x1 = 2.0f * versor->s0 * versor->x1;
+ const double s0x2 = 2.0f * versor->s0 * versor->x2;
+ const double s0x3 = 2.0f * versor->s0 * versor->x3;
+
+ const double x1x2 = 2.0f * versor->x1 * versor->x2;
+ const double x1x3 = 2.0f * versor->x1 * versor->x3;
+ const double x2x3 = 2.0f * versor->x2 * versor->x3;
+
+ const double r1c2 = x1x2 + s0x3;
+ const double r2c3 = x2x3 + s0x1;
+ const double r3c1 = x1x3 + s0x2;
+
+ const double r1c1 = (s0s0 + x1x1) - (x2x2 + x3x3);
+ const double r2c2 = (s0s0 + x2x2) - (x1x1 + x3x3);
+ const double r3c3 = (s0s0 + x3x3) - (x1x1 + x2x2);
+
+ const double r2c1 = x1x2 - s0x3;
+ const double r3c2 = x2x3 - s0x1;
+ const double r1c3 = x1x3 - s0x2;
+
+ const double x1 = r1c1 * vector->x1 + r1c2 * vector->x2 + r1c3 * vector->x3;
+ const double x2 = r2c1 * vector->x1 + r2c2 * vector->x2 + r2c3 * vector->x3;
+ const double x3 = r3c1 * vector->x1 + r3c2 * vector->x2 + r3c3 * vector->x3;
+
+ result->x1 = x1;
+ result->x2 = x2;
+ result->x3 = x3;
+}
+
+#endif