Browse Source

Add `f16` support to core:math/linalg

gingerBill 4 years ago
parent
commit
0fc04a939e

+ 18 - 3
core/math/linalg/general.odin

@@ -47,6 +47,9 @@ vector_dot :: proc(a, b: $T/[$N]$E) -> (c: E) where IS_NUMERIC(E) {
 	}
 	}
 	return;
 	return;
 }
 }
+quaternion64_dot :: proc(a, b: $T/quaternion64) -> (c: f16) {
+	return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z;
+}
 quaternion128_dot :: proc(a, b: $T/quaternion128) -> (c: f32) {
 quaternion128_dot :: proc(a, b: $T/quaternion128) -> (c: f32) {
 	return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z;
 	return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z;
 }
 }
@@ -54,7 +57,7 @@ quaternion256_dot :: proc(a, b: $T/quaternion256) -> (c: f64) {
 	return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z;
 	return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z;
 }
 }
 
 
-dot :: proc{scalar_dot, vector_dot, quaternion128_dot, quaternion256_dot};
+dot :: proc{scalar_dot, vector_dot, quaternion64_dot, quaternion128_dot, quaternion256_dot};
 
 
 inner_product :: dot;
 inner_product :: dot;
 outer_product :: proc(a: $A/[$M]$E, b: $B/[$N]E) -> (out: [M][N]E) where IS_NUMERIC(E) {
 outer_product :: proc(a: $A/[$M]$E, b: $B/[$N]E) -> (out: [M][N]E) where IS_NUMERIC(E) {
@@ -230,6 +233,16 @@ matrix_mul_vector :: proc(a: $A/[$I][$J]$E, b: $B/[I]E) -> (c: B)
 quaternion_mul_quaternion :: proc(q1, q2: $Q) -> Q where IS_QUATERNION(Q) {
 quaternion_mul_quaternion :: proc(q1, q2: $Q) -> Q where IS_QUATERNION(Q) {
 	return q1 * q2;
 	return q1 * q2;
 }
 }
+
+quaternion64_mul_vector3 :: proc(q: $Q/quaternion64, v: $V/[3]$F/f16) -> V {
+	Raw_Quaternion :: struct {xyz: [3]f16, r: f16};
+
+	q := transmute(Raw_Quaternion)q;
+	v := transmute([3]f16)v;
+
+	t := cross(2*q.xyz, v);
+	return V(v + q.r*t + cross(q.xyz, t));
+}
 quaternion128_mul_vector3 :: proc(q: $Q/quaternion128, v: $V/[3]$F/f32) -> V {
 quaternion128_mul_vector3 :: proc(q: $Q/quaternion128, v: $V/[3]$F/f32) -> V {
 	Raw_Quaternion :: struct {xyz: [3]f32, r: f32};
 	Raw_Quaternion :: struct {xyz: [3]f32, r: f32};
 
 
@@ -239,7 +252,6 @@ quaternion128_mul_vector3 :: proc(q: $Q/quaternion128, v: $V/[3]$F/f32) -> V {
 	t := cross(2*q.xyz, v);
 	t := cross(2*q.xyz, v);
 	return V(v + q.r*t + cross(q.xyz, t));
 	return V(v + q.r*t + cross(q.xyz, t));
 }
 }
-
 quaternion256_mul_vector3 :: proc(q: $Q/quaternion256, v: $V/[3]$F/f64) -> V {
 quaternion256_mul_vector3 :: proc(q: $Q/quaternion256, v: $V/[3]$F/f64) -> V {
 	Raw_Quaternion :: struct {xyz: [3]f64, r: f64};
 	Raw_Quaternion :: struct {xyz: [3]f64, r: f64};
 
 
@@ -249,12 +261,13 @@ quaternion256_mul_vector3 :: proc(q: $Q/quaternion256, v: $V/[3]$F/f64) -> V {
 	t := cross(2*q.xyz, v);
 	t := cross(2*q.xyz, v);
 	return V(v + q.r*t + cross(q.xyz, t));
 	return V(v + q.r*t + cross(q.xyz, t));
 }
 }
-quaternion_mul_vector3 :: proc{quaternion128_mul_vector3, quaternion256_mul_vector3};
+quaternion_mul_vector3 :: proc{quaternion64_mul_vector3, quaternion128_mul_vector3, quaternion256_mul_vector3};
 
 
 mul :: proc{
 mul :: proc{
 	matrix_mul,
 	matrix_mul,
 	matrix_mul_differ,
 	matrix_mul_differ,
 	matrix_mul_vector,
 	matrix_mul_vector,
+	quaternion64_mul_vector3,
 	quaternion128_mul_vector3,
 	quaternion128_mul_vector3,
 	quaternion256_mul_vector3,
 	quaternion256_mul_vector3,
 	quaternion_mul_quaternion,
 	quaternion_mul_quaternion,
@@ -347,7 +360,9 @@ to_u32  :: #force_inline proc(v: $A/[$N]$T) -> [N]u32  { return array_cast(v, u3
 to_u64  :: #force_inline proc(v: $A/[$N]$T) -> [N]u64  { return array_cast(v, u64);  }
 to_u64  :: #force_inline proc(v: $A/[$N]$T) -> [N]u64  { return array_cast(v, u64);  }
 to_uint :: #force_inline proc(v: $A/[$N]$T) -> [N]uint { return array_cast(v, uint); }
 to_uint :: #force_inline proc(v: $A/[$N]$T) -> [N]uint { return array_cast(v, uint); }
 
 
+to_complex32     :: #force_inline proc(v: $A/[$N]$T) -> [N]complex32     { return array_cast(v, complex32);     }
 to_complex64     :: #force_inline proc(v: $A/[$N]$T) -> [N]complex64     { return array_cast(v, complex64);     }
 to_complex64     :: #force_inline proc(v: $A/[$N]$T) -> [N]complex64     { return array_cast(v, complex64);     }
 to_complex128    :: #force_inline proc(v: $A/[$N]$T) -> [N]complex128    { return array_cast(v, complex128);    }
 to_complex128    :: #force_inline proc(v: $A/[$N]$T) -> [N]complex128    { return array_cast(v, complex128);    }
+to_quaternion64  :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion64 { return array_cast(v, quaternion64); }
 to_quaternion128 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion128 { return array_cast(v, quaternion128); }
 to_quaternion128 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion128 { return array_cast(v, quaternion128); }
 to_quaternion256 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion256 { return array_cast(v, quaternion256); }
 to_quaternion256 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion256 { return array_cast(v, quaternion256); }

File diff suppressed because it is too large
+ 552 - 6
core/math/linalg/specific.odin


+ 100 - 100
core/math/linalg/specific_euler_angles.odin

@@ -19,109 +19,109 @@ Euler_Angle_Order :: enum {
 }
 }
 
 
 
 
-quaternion_from_euler_angles       :: proc{quaternion_from_euler_angles_f32, quaternion_from_euler_angles_f64};
-quaternion_from_euler_angle_x      :: proc{quaternion_from_euler_angle_x_f32, quaternion_from_euler_angle_x_f64};
-quaternion_from_euler_angle_y      :: proc{quaternion_from_euler_angle_y_f32, quaternion_from_euler_angle_y_f64};
-quaternion_from_euler_angle_z      :: proc{quaternion_from_euler_angle_z_f32, quaternion_from_euler_angle_z_f64};
-quaternion_from_pitch_yaw_roll     :: proc{quaternion_from_pitch_yaw_roll_f32, quaternion_from_pitch_yaw_roll_f64};
+quaternion_from_euler_angles       :: proc{quaternion_from_euler_angles_f16,       quaternion_from_euler_angles_f32,       quaternion_from_euler_angles_f64};
+quaternion_from_euler_angle_x      :: proc{quaternion_from_euler_angle_x_f16,      quaternion_from_euler_angle_x_f32,      quaternion_from_euler_angle_x_f64};
+quaternion_from_euler_angle_y      :: proc{quaternion_from_euler_angle_y_f16,      quaternion_from_euler_angle_y_f32,      quaternion_from_euler_angle_y_f64};
+quaternion_from_euler_angle_z      :: proc{quaternion_from_euler_angle_z_f16,      quaternion_from_euler_angle_z_f32,      quaternion_from_euler_angle_z_f64};
+quaternion_from_pitch_yaw_roll     :: proc{quaternion_from_pitch_yaw_roll_f16,     quaternion_from_pitch_yaw_roll_f32,     quaternion_from_pitch_yaw_roll_f64};
 
 
-euler_angles_from_quaternion       :: proc{euler_angles_from_quaternion_f32, euler_angles_from_quaternion_f64};
-euler_angles_xyz_from_quaternion   :: proc{euler_angles_xyz_from_quaternion_f32, euler_angles_xyz_from_quaternion_f64};
-euler_angles_yxz_from_quaternion   :: proc{euler_angles_yxz_from_quaternion_f32, euler_angles_yxz_from_quaternion_f64};
-euler_angles_xzx_from_quaternion   :: proc{euler_angles_xzx_from_quaternion_f32, euler_angles_xzx_from_quaternion_f64};
-euler_angles_xyx_from_quaternion   :: proc{euler_angles_xyx_from_quaternion_f32, euler_angles_xyx_from_quaternion_f64};
-euler_angles_yxy_from_quaternion   :: proc{euler_angles_yxy_from_quaternion_f32, euler_angles_yxy_from_quaternion_f64};
-euler_angles_yzy_from_quaternion   :: proc{euler_angles_yzy_from_quaternion_f32, euler_angles_yzy_from_quaternion_f64};
-euler_angles_zyz_from_quaternion   :: proc{euler_angles_zyz_from_quaternion_f32, euler_angles_zyz_from_quaternion_f64};
-euler_angles_zxz_from_quaternion   :: proc{euler_angles_zxz_from_quaternion_f32, euler_angles_zxz_from_quaternion_f64};
-euler_angles_xzy_from_quaternion   :: proc{euler_angles_xzy_from_quaternion_f32, euler_angles_xzy_from_quaternion_f64};
-euler_angles_yzx_from_quaternion   :: proc{euler_angles_yzx_from_quaternion_f32, euler_angles_yzx_from_quaternion_f64};
-euler_angles_zyx_from_quaternion   :: proc{euler_angles_zyx_from_quaternion_f32, euler_angles_zyx_from_quaternion_f64};
-euler_angles_zxy_from_quaternion   :: proc{euler_angles_zxy_from_quaternion_f32, euler_angles_zxy_from_quaternion_f64};
+euler_angles_from_quaternion       :: proc{euler_angles_from_quaternion_f16,       euler_angles_from_quaternion_f32,       euler_angles_from_quaternion_f64};
+euler_angles_xyz_from_quaternion   :: proc{euler_angles_xyz_from_quaternion_f16,   euler_angles_xyz_from_quaternion_f32,   euler_angles_xyz_from_quaternion_f64};
+euler_angles_yxz_from_quaternion   :: proc{euler_angles_yxz_from_quaternion_f16,   euler_angles_yxz_from_quaternion_f32,   euler_angles_yxz_from_quaternion_f64};
+euler_angles_xzx_from_quaternion   :: proc{euler_angles_xzx_from_quaternion_f16,   euler_angles_xzx_from_quaternion_f32,   euler_angles_xzx_from_quaternion_f64};
+euler_angles_xyx_from_quaternion   :: proc{euler_angles_xyx_from_quaternion_f16,   euler_angles_xyx_from_quaternion_f32,   euler_angles_xyx_from_quaternion_f64};
+euler_angles_yxy_from_quaternion   :: proc{euler_angles_yxy_from_quaternion_f16,   euler_angles_yxy_from_quaternion_f32,   euler_angles_yxy_from_quaternion_f64};
+euler_angles_yzy_from_quaternion   :: proc{euler_angles_yzy_from_quaternion_f16,   euler_angles_yzy_from_quaternion_f32,   euler_angles_yzy_from_quaternion_f64};
+euler_angles_zyz_from_quaternion   :: proc{euler_angles_zyz_from_quaternion_f16,   euler_angles_zyz_from_quaternion_f32,   euler_angles_zyz_from_quaternion_f64};
+euler_angles_zxz_from_quaternion   :: proc{euler_angles_zxz_from_quaternion_f16,   euler_angles_zxz_from_quaternion_f32,   euler_angles_zxz_from_quaternion_f64};
+euler_angles_xzy_from_quaternion   :: proc{euler_angles_xzy_from_quaternion_f16,   euler_angles_xzy_from_quaternion_f32,   euler_angles_xzy_from_quaternion_f64};
+euler_angles_yzx_from_quaternion   :: proc{euler_angles_yzx_from_quaternion_f16,   euler_angles_yzx_from_quaternion_f32,   euler_angles_yzx_from_quaternion_f64};
+euler_angles_zyx_from_quaternion   :: proc{euler_angles_zyx_from_quaternion_f16,   euler_angles_zyx_from_quaternion_f32,   euler_angles_zyx_from_quaternion_f64};
+euler_angles_zxy_from_quaternion   :: proc{euler_angles_zxy_from_quaternion_f16,   euler_angles_zxy_from_quaternion_f32,   euler_angles_zxy_from_quaternion_f64};
 
 
-roll_from_quaternion               :: proc{roll_from_quaternion_f32, roll_from_quaternion_f64};
-pitch_from_quaternion              :: proc{pitch_from_quaternion_f32, pitch_from_quaternion_f64};
-yaw_from_quaternion                :: proc{yaw_from_quaternion_f32, yaw_from_quaternion_f64};
-pitch_yaw_roll_from_quaternion     :: proc{pitch_yaw_roll_from_quaternion_f32, pitch_yaw_roll_from_quaternion_f64};
+roll_from_quaternion               :: proc{roll_from_quaternion_f16,               roll_from_quaternion_f32,               roll_from_quaternion_f64};
+pitch_from_quaternion              :: proc{pitch_from_quaternion_f16,              pitch_from_quaternion_f32,              pitch_from_quaternion_f64};
+yaw_from_quaternion                :: proc{yaw_from_quaternion_f16,                yaw_from_quaternion_f32,                yaw_from_quaternion_f64};
+pitch_yaw_roll_from_quaternion     :: proc{pitch_yaw_roll_from_quaternion_f16,     pitch_yaw_roll_from_quaternion_f32,     pitch_yaw_roll_from_quaternion_f64};
 
 
-matrix3_from_euler_angles          :: proc{matrix3_from_euler_angles_f32, matrix3_from_euler_angles_f64};
-matrix3_from_euler_angle_x         :: proc{matrix3_from_euler_angle_x_f32, matrix3_from_euler_angle_x_f64};
-matrix3_from_euler_angle_y         :: proc{matrix3_from_euler_angle_y_f32, matrix3_from_euler_angle_y_f64};
-matrix3_from_euler_angle_z         :: proc{matrix3_from_euler_angle_z_f32, matrix3_from_euler_angle_z_f64};
-matrix3_from_derived_euler_angle_x :: proc{matrix3_from_derived_euler_angle_x_f32, matrix3_from_derived_euler_angle_x_f64};
-matrix3_from_derived_euler_angle_y :: proc{matrix3_from_derived_euler_angle_y_f32, matrix3_from_derived_euler_angle_y_f64};
-matrix3_from_derived_euler_angle_z :: proc{matrix3_from_derived_euler_angle_z_f32, matrix3_from_derived_euler_angle_z_f64};
-matrix3_from_euler_angles_xy       :: proc{matrix3_from_euler_angles_xy_f32, matrix3_from_euler_angles_xy_f64};
-matrix3_from_euler_angles_yx       :: proc{matrix3_from_euler_angles_yx_f32, matrix3_from_euler_angles_yx_f64};
-matrix3_from_euler_angles_xz       :: proc{matrix3_from_euler_angles_xz_f32, matrix3_from_euler_angles_xz_f64};
-matrix3_from_euler_angles_zx       :: proc{matrix3_from_euler_angles_zx_f32, matrix3_from_euler_angles_zx_f64};
-matrix3_from_euler_angles_yz       :: proc{matrix3_from_euler_angles_yz_f32, matrix3_from_euler_angles_yz_f64};
-matrix3_from_euler_angles_zy       :: proc{matrix3_from_euler_angles_zy_f32, matrix3_from_euler_angles_zy_f64};
-matrix3_from_euler_angles_xyz      :: proc{matrix3_from_euler_angles_xyz_f32, matrix3_from_euler_angles_xyz_f64};
-matrix3_from_euler_angles_yxz      :: proc{matrix3_from_euler_angles_yxz_f32, matrix3_from_euler_angles_yxz_f64};
-matrix3_from_euler_angles_xzx      :: proc{matrix3_from_euler_angles_xzx_f32, matrix3_from_euler_angles_xzx_f64};
-matrix3_from_euler_angles_xyx      :: proc{matrix3_from_euler_angles_xyx_f32, matrix3_from_euler_angles_xyx_f64};
-matrix3_from_euler_angles_yxy      :: proc{matrix3_from_euler_angles_yxy_f32, matrix3_from_euler_angles_yxy_f64};
-matrix3_from_euler_angles_yzy      :: proc{matrix3_from_euler_angles_yzy_f32, matrix3_from_euler_angles_yzy_f64};
-matrix3_from_euler_angles_zyz      :: proc{matrix3_from_euler_angles_zyz_f32, matrix3_from_euler_angles_zyz_f64};
-matrix3_from_euler_angles_zxz      :: proc{matrix3_from_euler_angles_zxz_f32, matrix3_from_euler_angles_zxz_f64};
-matrix3_from_euler_angles_xzy      :: proc{matrix3_from_euler_angles_xzy_f32, matrix3_from_euler_angles_xzy_f64};
-matrix3_from_euler_angles_yzx      :: proc{matrix3_from_euler_angles_yzx_f32, matrix3_from_euler_angles_yzx_f64};
-matrix3_from_euler_angles_zyx      :: proc{matrix3_from_euler_angles_zyx_f32, matrix3_from_euler_angles_zyx_f64};
-matrix3_from_euler_angles_zxy      :: proc{matrix3_from_euler_angles_zxy_f32, matrix3_from_euler_angles_zxy_f64};
-matrix3_from_yaw_pitch_roll        :: proc{matrix3_from_yaw_pitch_roll_f32, matrix3_from_yaw_pitch_roll_f64};
+matrix3_from_euler_angles          :: proc{matrix3_from_euler_angles_f16,          matrix3_from_euler_angles_f32,          matrix3_from_euler_angles_f64};
+matrix3_from_euler_angle_x         :: proc{matrix3_from_euler_angle_x_f16,         matrix3_from_euler_angle_x_f32,         matrix3_from_euler_angle_x_f64};
+matrix3_from_euler_angle_y         :: proc{matrix3_from_euler_angle_y_f16,         matrix3_from_euler_angle_y_f32,         matrix3_from_euler_angle_y_f64};
+matrix3_from_euler_angle_z         :: proc{matrix3_from_euler_angle_z_f16,         matrix3_from_euler_angle_z_f32,         matrix3_from_euler_angle_z_f64};
+matrix3_from_derived_euler_angle_x :: proc{matrix3_from_derived_euler_angle_x_f16, matrix3_from_derived_euler_angle_x_f32, matrix3_from_derived_euler_angle_x_f64};
+matrix3_from_derived_euler_angle_y :: proc{matrix3_from_derived_euler_angle_y_f16, matrix3_from_derived_euler_angle_y_f32, matrix3_from_derived_euler_angle_y_f64};
+matrix3_from_derived_euler_angle_z :: proc{matrix3_from_derived_euler_angle_z_f16, matrix3_from_derived_euler_angle_z_f32, matrix3_from_derived_euler_angle_z_f64};
+matrix3_from_euler_angles_xy       :: proc{matrix3_from_euler_angles_xy_f16,       matrix3_from_euler_angles_xy_f32,       matrix3_from_euler_angles_xy_f64};
+matrix3_from_euler_angles_yx       :: proc{matrix3_from_euler_angles_yx_f16,       matrix3_from_euler_angles_yx_f32,       matrix3_from_euler_angles_yx_f64};
+matrix3_from_euler_angles_xz       :: proc{matrix3_from_euler_angles_xz_f16,       matrix3_from_euler_angles_xz_f32,       matrix3_from_euler_angles_xz_f64};
+matrix3_from_euler_angles_zx       :: proc{matrix3_from_euler_angles_zx_f16,       matrix3_from_euler_angles_zx_f32,       matrix3_from_euler_angles_zx_f64};
+matrix3_from_euler_angles_yz       :: proc{matrix3_from_euler_angles_yz_f16,       matrix3_from_euler_angles_yz_f32,       matrix3_from_euler_angles_yz_f64};
+matrix3_from_euler_angles_zy       :: proc{matrix3_from_euler_angles_zy_f16,       matrix3_from_euler_angles_zy_f32,       matrix3_from_euler_angles_zy_f64};
+matrix3_from_euler_angles_xyz      :: proc{matrix3_from_euler_angles_xyz_f16,      matrix3_from_euler_angles_xyz_f32,      matrix3_from_euler_angles_xyz_f64};
+matrix3_from_euler_angles_yxz      :: proc{matrix3_from_euler_angles_yxz_f16,      matrix3_from_euler_angles_yxz_f32,      matrix3_from_euler_angles_yxz_f64};
+matrix3_from_euler_angles_xzx      :: proc{matrix3_from_euler_angles_xzx_f16,      matrix3_from_euler_angles_xzx_f32,      matrix3_from_euler_angles_xzx_f64};
+matrix3_from_euler_angles_xyx      :: proc{matrix3_from_euler_angles_xyx_f16,      matrix3_from_euler_angles_xyx_f32,      matrix3_from_euler_angles_xyx_f64};
+matrix3_from_euler_angles_yxy      :: proc{matrix3_from_euler_angles_yxy_f16,      matrix3_from_euler_angles_yxy_f32,      matrix3_from_euler_angles_yxy_f64};
+matrix3_from_euler_angles_yzy      :: proc{matrix3_from_euler_angles_yzy_f16,      matrix3_from_euler_angles_yzy_f32,      matrix3_from_euler_angles_yzy_f64};
+matrix3_from_euler_angles_zyz      :: proc{matrix3_from_euler_angles_zyz_f16,      matrix3_from_euler_angles_zyz_f32,      matrix3_from_euler_angles_zyz_f64};
+matrix3_from_euler_angles_zxz      :: proc{matrix3_from_euler_angles_zxz_f16,      matrix3_from_euler_angles_zxz_f32,      matrix3_from_euler_angles_zxz_f64};
+matrix3_from_euler_angles_xzy      :: proc{matrix3_from_euler_angles_xzy_f16,      matrix3_from_euler_angles_xzy_f32,      matrix3_from_euler_angles_xzy_f64};
+matrix3_from_euler_angles_yzx      :: proc{matrix3_from_euler_angles_yzx_f16,      matrix3_from_euler_angles_yzx_f32,      matrix3_from_euler_angles_yzx_f64};
+matrix3_from_euler_angles_zyx      :: proc{matrix3_from_euler_angles_zyx_f16,      matrix3_from_euler_angles_zyx_f32,      matrix3_from_euler_angles_zyx_f64};
+matrix3_from_euler_angles_zxy      :: proc{matrix3_from_euler_angles_zxy_f16,      matrix3_from_euler_angles_zxy_f32,      matrix3_from_euler_angles_zxy_f64};
+matrix3_from_yaw_pitch_roll        :: proc{matrix3_from_yaw_pitch_roll_f16,        matrix3_from_yaw_pitch_roll_f32,        matrix3_from_yaw_pitch_roll_f64};
 
 
-euler_angles_from_matrix3          :: proc{euler_angles_from_matrix3_f32, euler_angles_from_matrix3_f64};
-euler_angles_xyz_from_matrix3      :: proc{euler_angles_xyz_from_matrix3_f32, euler_angles_xyz_from_matrix3_f64};
-euler_angles_yxz_from_matrix3      :: proc{euler_angles_yxz_from_matrix3_f32, euler_angles_yxz_from_matrix3_f64};
-euler_angles_xzx_from_matrix3      :: proc{euler_angles_xzx_from_matrix3_f32, euler_angles_xzx_from_matrix3_f64};
-euler_angles_xyx_from_matrix3      :: proc{euler_angles_xyx_from_matrix3_f32, euler_angles_xyx_from_matrix3_f64};
-euler_angles_yxy_from_matrix3      :: proc{euler_angles_yxy_from_matrix3_f32, euler_angles_yxy_from_matrix3_f64};
-euler_angles_yzy_from_matrix3      :: proc{euler_angles_yzy_from_matrix3_f32, euler_angles_yzy_from_matrix3_f64};
-euler_angles_zyz_from_matrix3      :: proc{euler_angles_zyz_from_matrix3_f32, euler_angles_zyz_from_matrix3_f64};
-euler_angles_zxz_from_matrix3      :: proc{euler_angles_zxz_from_matrix3_f32, euler_angles_zxz_from_matrix3_f64};
-euler_angles_xzy_from_matrix3      :: proc{euler_angles_xzy_from_matrix3_f32, euler_angles_xzy_from_matrix3_f64};
-euler_angles_yzx_from_matrix3      :: proc{euler_angles_yzx_from_matrix3_f32, euler_angles_yzx_from_matrix3_f64};
-euler_angles_zyx_from_matrix3      :: proc{euler_angles_zyx_from_matrix3_f32, euler_angles_zyx_from_matrix3_f64};
-euler_angles_zxy_from_matrix3      :: proc{euler_angles_zxy_from_matrix3_f32, euler_angles_zxy_from_matrix3_f64};
+euler_angles_from_matrix3          :: proc{euler_angles_from_matrix3_f16,          euler_angles_from_matrix3_f32,          euler_angles_from_matrix3_f64};
+euler_angles_xyz_from_matrix3      :: proc{euler_angles_xyz_from_matrix3_f16,      euler_angles_xyz_from_matrix3_f32,      euler_angles_xyz_from_matrix3_f64};
+euler_angles_yxz_from_matrix3      :: proc{euler_angles_yxz_from_matrix3_f16,      euler_angles_yxz_from_matrix3_f32,      euler_angles_yxz_from_matrix3_f64};
+euler_angles_xzx_from_matrix3      :: proc{euler_angles_xzx_from_matrix3_f16,      euler_angles_xzx_from_matrix3_f32,      euler_angles_xzx_from_matrix3_f64};
+euler_angles_xyx_from_matrix3      :: proc{euler_angles_xyx_from_matrix3_f16,      euler_angles_xyx_from_matrix3_f32,      euler_angles_xyx_from_matrix3_f64};
+euler_angles_yxy_from_matrix3      :: proc{euler_angles_yxy_from_matrix3_f16,      euler_angles_yxy_from_matrix3_f32,      euler_angles_yxy_from_matrix3_f64};
+euler_angles_yzy_from_matrix3      :: proc{euler_angles_yzy_from_matrix3_f16,      euler_angles_yzy_from_matrix3_f32,      euler_angles_yzy_from_matrix3_f64};
+euler_angles_zyz_from_matrix3      :: proc{euler_angles_zyz_from_matrix3_f16,      euler_angles_zyz_from_matrix3_f32,      euler_angles_zyz_from_matrix3_f64};
+euler_angles_zxz_from_matrix3      :: proc{euler_angles_zxz_from_matrix3_f16,      euler_angles_zxz_from_matrix3_f32,      euler_angles_zxz_from_matrix3_f64};
+euler_angles_xzy_from_matrix3      :: proc{euler_angles_xzy_from_matrix3_f16,      euler_angles_xzy_from_matrix3_f32,      euler_angles_xzy_from_matrix3_f64};
+euler_angles_yzx_from_matrix3      :: proc{euler_angles_yzx_from_matrix3_f16,      euler_angles_yzx_from_matrix3_f32,      euler_angles_yzx_from_matrix3_f64};
+euler_angles_zyx_from_matrix3      :: proc{euler_angles_zyx_from_matrix3_f16,      euler_angles_zyx_from_matrix3_f32,      euler_angles_zyx_from_matrix3_f64};
+euler_angles_zxy_from_matrix3      :: proc{euler_angles_zxy_from_matrix3_f16,      euler_angles_zxy_from_matrix3_f32,      euler_angles_zxy_from_matrix3_f64};
 
 
-matrix4_from_euler_angles          :: proc{matrix4_from_euler_angles_f32, matrix4_from_euler_angles_f64};
-matrix4_from_euler_angle_x         :: proc{matrix4_from_euler_angle_x_f32, matrix4_from_euler_angle_x_f64};
-matrix4_from_euler_angle_y         :: proc{matrix4_from_euler_angle_y_f32, matrix4_from_euler_angle_y_f64};
-matrix4_from_euler_angle_z         :: proc{matrix4_from_euler_angle_z_f32, matrix4_from_euler_angle_z_f64};
-matrix4_from_derived_euler_angle_x :: proc{matrix4_from_derived_euler_angle_x_f32, matrix4_from_derived_euler_angle_x_f64};
-matrix4_from_derived_euler_angle_y :: proc{matrix4_from_derived_euler_angle_y_f32, matrix4_from_derived_euler_angle_y_f64};
-matrix4_from_derived_euler_angle_z :: proc{matrix4_from_derived_euler_angle_z_f32, matrix4_from_derived_euler_angle_z_f64};
-matrix4_from_euler_angles_xy       :: proc{matrix4_from_euler_angles_xy_f32, matrix4_from_euler_angles_xy_f64};
-matrix4_from_euler_angles_yx       :: proc{matrix4_from_euler_angles_yx_f32, matrix4_from_euler_angles_yx_f64};
-matrix4_from_euler_angles_xz       :: proc{matrix4_from_euler_angles_xz_f32, matrix4_from_euler_angles_xz_f64};
-matrix4_from_euler_angles_zx       :: proc{matrix4_from_euler_angles_zx_f32, matrix4_from_euler_angles_zx_f64};
-matrix4_from_euler_angles_yz       :: proc{matrix4_from_euler_angles_yz_f32, matrix4_from_euler_angles_yz_f64};
-matrix4_from_euler_angles_zy       :: proc{matrix4_from_euler_angles_zy_f32, matrix4_from_euler_angles_zy_f64};
-matrix4_from_euler_angles_xyz      :: proc{matrix4_from_euler_angles_xyz_f32, matrix4_from_euler_angles_xyz_f64};
-matrix4_from_euler_angles_yxz      :: proc{matrix4_from_euler_angles_yxz_f32, matrix4_from_euler_angles_yxz_f64};
-matrix4_from_euler_angles_xzx      :: proc{matrix4_from_euler_angles_xzx_f32, matrix4_from_euler_angles_xzx_f64};
-matrix4_from_euler_angles_xyx      :: proc{matrix4_from_euler_angles_xyx_f32, matrix4_from_euler_angles_xyx_f64};
-matrix4_from_euler_angles_yxy      :: proc{matrix4_from_euler_angles_yxy_f32, matrix4_from_euler_angles_yxy_f64};
-matrix4_from_euler_angles_yzy      :: proc{matrix4_from_euler_angles_yzy_f32, matrix4_from_euler_angles_yzy_f64};
-matrix4_from_euler_angles_zyz      :: proc{matrix4_from_euler_angles_zyz_f32, matrix4_from_euler_angles_zyz_f64};
-matrix4_from_euler_angles_zxz      :: proc{matrix4_from_euler_angles_zxz_f32, matrix4_from_euler_angles_zxz_f64};
-matrix4_from_euler_angles_xzy      :: proc{matrix4_from_euler_angles_xzy_f32, matrix4_from_euler_angles_xzy_f64};
-matrix4_from_euler_angles_yzx      :: proc{matrix4_from_euler_angles_yzx_f32, matrix4_from_euler_angles_yzx_f64};
-matrix4_from_euler_angles_zyx      :: proc{matrix4_from_euler_angles_zyx_f32, matrix4_from_euler_angles_zyx_f64};
-matrix4_from_euler_angles_zxy      :: proc{matrix4_from_euler_angles_zxy_f32, matrix4_from_euler_angles_zxy_f64};
-matrix4_from_yaw_pitch_roll        :: proc{matrix4_from_yaw_pitch_roll_f32, matrix4_from_yaw_pitch_roll_f64};
+matrix4_from_euler_angles          :: proc{matrix4_from_euler_angles_f16,          matrix4_from_euler_angles_f32,          matrix4_from_euler_angles_f64};
+matrix4_from_euler_angle_x         :: proc{matrix4_from_euler_angle_x_f16,         matrix4_from_euler_angle_x_f32,         matrix4_from_euler_angle_x_f64};
+matrix4_from_euler_angle_y         :: proc{matrix4_from_euler_angle_y_f16,         matrix4_from_euler_angle_y_f32,         matrix4_from_euler_angle_y_f64};
+matrix4_from_euler_angle_z         :: proc{matrix4_from_euler_angle_z_f16,         matrix4_from_euler_angle_z_f32,         matrix4_from_euler_angle_z_f64};
+matrix4_from_derived_euler_angle_x :: proc{matrix4_from_derived_euler_angle_x_f16, matrix4_from_derived_euler_angle_x_f32, matrix4_from_derived_euler_angle_x_f64};
+matrix4_from_derived_euler_angle_y :: proc{matrix4_from_derived_euler_angle_y_f16, matrix4_from_derived_euler_angle_y_f32, matrix4_from_derived_euler_angle_y_f64};
+matrix4_from_derived_euler_angle_z :: proc{matrix4_from_derived_euler_angle_z_f16, matrix4_from_derived_euler_angle_z_f32, matrix4_from_derived_euler_angle_z_f64};
+matrix4_from_euler_angles_xy       :: proc{matrix4_from_euler_angles_xy_f16,       matrix4_from_euler_angles_xy_f32,       matrix4_from_euler_angles_xy_f64};
+matrix4_from_euler_angles_yx       :: proc{matrix4_from_euler_angles_yx_f16,       matrix4_from_euler_angles_yx_f32,       matrix4_from_euler_angles_yx_f64};
+matrix4_from_euler_angles_xz       :: proc{matrix4_from_euler_angles_xz_f16,       matrix4_from_euler_angles_xz_f32,       matrix4_from_euler_angles_xz_f64};
+matrix4_from_euler_angles_zx       :: proc{matrix4_from_euler_angles_zx_f16,       matrix4_from_euler_angles_zx_f32,       matrix4_from_euler_angles_zx_f64};
+matrix4_from_euler_angles_yz       :: proc{matrix4_from_euler_angles_yz_f16,       matrix4_from_euler_angles_yz_f32,       matrix4_from_euler_angles_yz_f64};
+matrix4_from_euler_angles_zy       :: proc{matrix4_from_euler_angles_zy_f16,       matrix4_from_euler_angles_zy_f32,       matrix4_from_euler_angles_zy_f64};
+matrix4_from_euler_angles_xyz      :: proc{matrix4_from_euler_angles_xyz_f16,      matrix4_from_euler_angles_xyz_f32,      matrix4_from_euler_angles_xyz_f64};
+matrix4_from_euler_angles_yxz      :: proc{matrix4_from_euler_angles_yxz_f16,      matrix4_from_euler_angles_yxz_f32,      matrix4_from_euler_angles_yxz_f64};
+matrix4_from_euler_angles_xzx      :: proc{matrix4_from_euler_angles_xzx_f16,      matrix4_from_euler_angles_xzx_f32,      matrix4_from_euler_angles_xzx_f64};
+matrix4_from_euler_angles_xyx      :: proc{matrix4_from_euler_angles_xyx_f16,      matrix4_from_euler_angles_xyx_f32,      matrix4_from_euler_angles_xyx_f64};
+matrix4_from_euler_angles_yxy      :: proc{matrix4_from_euler_angles_yxy_f16,      matrix4_from_euler_angles_yxy_f32,      matrix4_from_euler_angles_yxy_f64};
+matrix4_from_euler_angles_yzy      :: proc{matrix4_from_euler_angles_yzy_f16,      matrix4_from_euler_angles_yzy_f32,      matrix4_from_euler_angles_yzy_f64};
+matrix4_from_euler_angles_zyz      :: proc{matrix4_from_euler_angles_zyz_f16,      matrix4_from_euler_angles_zyz_f32,      matrix4_from_euler_angles_zyz_f64};
+matrix4_from_euler_angles_zxz      :: proc{matrix4_from_euler_angles_zxz_f16,      matrix4_from_euler_angles_zxz_f32,      matrix4_from_euler_angles_zxz_f64};
+matrix4_from_euler_angles_xzy      :: proc{matrix4_from_euler_angles_xzy_f16,      matrix4_from_euler_angles_xzy_f32,      matrix4_from_euler_angles_xzy_f64};
+matrix4_from_euler_angles_yzx      :: proc{matrix4_from_euler_angles_yzx_f16,      matrix4_from_euler_angles_yzx_f32,      matrix4_from_euler_angles_yzx_f64};
+matrix4_from_euler_angles_zyx      :: proc{matrix4_from_euler_angles_zyx_f16,      matrix4_from_euler_angles_zyx_f32,      matrix4_from_euler_angles_zyx_f64};
+matrix4_from_euler_angles_zxy      :: proc{matrix4_from_euler_angles_zxy_f16,      matrix4_from_euler_angles_zxy_f32,      matrix4_from_euler_angles_zxy_f64};
+matrix4_from_yaw_pitch_roll        :: proc{matrix4_from_yaw_pitch_roll_f16,        matrix4_from_yaw_pitch_roll_f32,        matrix4_from_yaw_pitch_roll_f64};
 
 
-euler_angles_from_matrix4          :: proc{euler_angles_from_matrix4_f32, euler_angles_from_matrix4_f64};
-euler_angles_xyz_from_matrix4      :: proc{euler_angles_xyz_from_matrix4_f32, euler_angles_xyz_from_matrix4_f64};
-euler_angles_yxz_from_matrix4      :: proc{euler_angles_yxz_from_matrix4_f32, euler_angles_yxz_from_matrix4_f64};
-euler_angles_xzx_from_matrix4      :: proc{euler_angles_xzx_from_matrix4_f32, euler_angles_xzx_from_matrix4_f64};
-euler_angles_xyx_from_matrix4      :: proc{euler_angles_xyx_from_matrix4_f32, euler_angles_xyx_from_matrix4_f64};
-euler_angles_yxy_from_matrix4      :: proc{euler_angles_yxy_from_matrix4_f32, euler_angles_yxy_from_matrix4_f64};
-euler_angles_yzy_from_matrix4      :: proc{euler_angles_yzy_from_matrix4_f32, euler_angles_yzy_from_matrix4_f64};
-euler_angles_zyz_from_matrix4      :: proc{euler_angles_zyz_from_matrix4_f32, euler_angles_zyz_from_matrix4_f64};
-euler_angles_zxz_from_matrix4      :: proc{euler_angles_zxz_from_matrix4_f32, euler_angles_zxz_from_matrix4_f64};
-euler_angles_xzy_from_matrix4      :: proc{euler_angles_xzy_from_matrix4_f32, euler_angles_xzy_from_matrix4_f64};
-euler_angles_yzx_from_matrix4      :: proc{euler_angles_yzx_from_matrix4_f32, euler_angles_yzx_from_matrix4_f64};
-euler_angles_zyx_from_matrix4      :: proc{euler_angles_zyx_from_matrix4_f32, euler_angles_zyx_from_matrix4_f64};
-euler_angles_zxy_from_matrix4      :: proc{euler_angles_zxy_from_matrix4_f32, euler_angles_zxy_from_matrix4_f64};
+euler_angles_from_matrix4          :: proc{euler_angles_from_matrix4_f16,          euler_angles_from_matrix4_f32,          euler_angles_from_matrix4_f64};
+euler_angles_xyz_from_matrix4      :: proc{euler_angles_xyz_from_matrix4_f16,      euler_angles_xyz_from_matrix4_f32,      euler_angles_xyz_from_matrix4_f64};
+euler_angles_yxz_from_matrix4      :: proc{euler_angles_yxz_from_matrix4_f16,      euler_angles_yxz_from_matrix4_f32,      euler_angles_yxz_from_matrix4_f64};
+euler_angles_xzx_from_matrix4      :: proc{euler_angles_xzx_from_matrix4_f16,      euler_angles_xzx_from_matrix4_f32,      euler_angles_xzx_from_matrix4_f64};
+euler_angles_xyx_from_matrix4      :: proc{euler_angles_xyx_from_matrix4_f16,      euler_angles_xyx_from_matrix4_f32,      euler_angles_xyx_from_matrix4_f64};
+euler_angles_yxy_from_matrix4      :: proc{euler_angles_yxy_from_matrix4_f16,      euler_angles_yxy_from_matrix4_f32,      euler_angles_yxy_from_matrix4_f64};
+euler_angles_yzy_from_matrix4      :: proc{euler_angles_yzy_from_matrix4_f16,      euler_angles_yzy_from_matrix4_f32,      euler_angles_yzy_from_matrix4_f64};
+euler_angles_zyz_from_matrix4      :: proc{euler_angles_zyz_from_matrix4_f16,      euler_angles_zyz_from_matrix4_f32,      euler_angles_zyz_from_matrix4_f64};
+euler_angles_zxz_from_matrix4      :: proc{euler_angles_zxz_from_matrix4_f16,      euler_angles_zxz_from_matrix4_f32,      euler_angles_zxz_from_matrix4_f64};
+euler_angles_xzy_from_matrix4      :: proc{euler_angles_xzy_from_matrix4_f16,      euler_angles_xzy_from_matrix4_f32,      euler_angles_xzy_from_matrix4_f64};
+euler_angles_yzx_from_matrix4      :: proc{euler_angles_yzx_from_matrix4_f16,      euler_angles_yzx_from_matrix4_f32,      euler_angles_yzx_from_matrix4_f64};
+euler_angles_zyx_from_matrix4      :: proc{euler_angles_zyx_from_matrix4_f16,      euler_angles_zyx_from_matrix4_f32,      euler_angles_zyx_from_matrix4_f64};
+euler_angles_zxy_from_matrix4      :: proc{euler_angles_zxy_from_matrix4_f16,      euler_angles_zxy_from_matrix4_f32,      euler_angles_zxy_from_matrix4_f64};

+ 1356 - 0
core/math/linalg/specific_euler_angles_f16.odin

@@ -0,0 +1,1356 @@
+package linalg
+
+import "core:math"
+
+euler_angles_from_matrix3_f16 :: proc(m: Matrix3f16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) {
+	switch order {
+	case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m);
+	case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m);
+	case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix3(m);
+	case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix3(m);
+	case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix3(m);
+	case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix3(m);
+	case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix3(m);
+	case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix3(m);
+	case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix3(m);
+	case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix3(m);
+	case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix3(m);
+	case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix3(m);
+	}
+	return;
+}
+euler_angles_from_matrix4_f16 :: proc(m: Matrix4f16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) {
+	switch order {
+	case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m);
+	case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m);
+	case .YXZ: t1, t2, t3 = euler_angles_yxz_from_matrix4(m);
+	case .YZX: t1, t2, t3 = euler_angles_yzx_from_matrix4(m);
+	case .ZXY: t1, t2, t3 = euler_angles_zxy_from_matrix4(m);
+	case .ZYX: t1, t2, t3 = euler_angles_zyx_from_matrix4(m);
+	case .XYX: t1, t2, t3 = euler_angles_xyx_from_matrix4(m);
+	case .XZX: t1, t2, t3 = euler_angles_xzx_from_matrix4(m);
+	case .YXY: t1, t2, t3 = euler_angles_yxy_from_matrix4(m);
+	case .YZY: t1, t2, t3 = euler_angles_yzy_from_matrix4(m);
+	case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_matrix4(m);
+	case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_matrix4(m);
+	}
+	return;
+}
+euler_angles_from_quaternion_f16 :: proc(m: Quaternionf16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) {
+	switch order {
+	case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m);
+	case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m);
+	case .YXZ: t1, t2, t3 = euler_angles_yxz_from_quaternion(m);
+	case .YZX: t1, t2, t3 = euler_angles_yzx_from_quaternion(m);
+	case .ZXY: t1, t2, t3 = euler_angles_zxy_from_quaternion(m);
+	case .ZYX: t1, t2, t3 = euler_angles_zyx_from_quaternion(m);
+	case .XYX: t1, t2, t3 = euler_angles_xyx_from_quaternion(m);
+	case .XZX: t1, t2, t3 = euler_angles_xzx_from_quaternion(m);
+	case .YXY: t1, t2, t3 = euler_angles_yxy_from_quaternion(m);
+	case .YZY: t1, t2, t3 = euler_angles_yzy_from_quaternion(m);
+	case .ZXZ: t1, t2, t3 = euler_angles_zxz_from_quaternion(m);
+	case .ZYZ: t1, t2, t3 = euler_angles_zyz_from_quaternion(m);
+	}
+	return;
+}
+
+matrix3_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> (m: Matrix3f16) {
+	switch order {
+	case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), Z(t3);
+	case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), Y(t3);
+	case .YXZ: return matrix3_from_euler_angles_yxz(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Z(t3);
+	case .YZX: return matrix3_from_euler_angles_yzx(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), X(t3);
+	case .ZXY: return matrix3_from_euler_angles_zxy(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Y(t3);
+	case .ZYX: return matrix3_from_euler_angles_zyx(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), X(t3);
+	case .XYX: return matrix3_from_euler_angles_xyx(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), X(t3);
+	case .XZX: return matrix3_from_euler_angles_xzx(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), X(t3);
+	case .YXY: return matrix3_from_euler_angles_yxy(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Y(t3);
+	case .YZY: return matrix3_from_euler_angles_yzy(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), Y(t3);
+	case .ZXZ: return matrix3_from_euler_angles_zxz(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Z(t3);
+	case .ZYZ: return matrix3_from_euler_angles_zyz(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), Z(t3);
+	}
+	return;
+}
+matrix4_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> (m: Matrix4f16) {
+	switch order {
+	case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), Z(t3);
+	case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), Y(t3);
+	case .YXZ: return matrix4_from_euler_angles_yxz(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Z(t3);
+	case .YZX: return matrix4_from_euler_angles_yzx(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), X(t3);
+	case .ZXY: return matrix4_from_euler_angles_zxy(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Y(t3);
+	case .ZYX: return matrix4_from_euler_angles_zyx(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), X(t3);
+	case .XYX: return matrix4_from_euler_angles_xyx(t1, t2, t3); // m1, m2, m3 = X(t1), Y(t2), X(t3);
+	case .XZX: return matrix4_from_euler_angles_xzx(t1, t2, t3); // m1, m2, m3 = X(t1), Z(t2), X(t3);
+	case .YXY: return matrix4_from_euler_angles_yxy(t1, t2, t3); // m1, m2, m3 = Y(t1), X(t2), Y(t3);
+	case .YZY: return matrix4_from_euler_angles_yzy(t1, t2, t3); // m1, m2, m3 = Y(t1), Z(t2), Y(t3);
+	case .ZXZ: return matrix4_from_euler_angles_zxz(t1, t2, t3); // m1, m2, m3 = Z(t1), X(t2), Z(t3);
+	case .ZYZ: return matrix4_from_euler_angles_zyz(t1, t2, t3); // m1, m2, m3 = Z(t1), Y(t2), Z(t3);
+	}
+	return;
+}
+
+quaternion_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> Quaternionf16 {
+	X :: quaternion_from_euler_angle_x;
+	Y :: quaternion_from_euler_angle_y;
+	Z :: quaternion_from_euler_angle_z;
+
+	q1, q2, q3: Quaternionf16;
+
+	switch order {
+	case .XYZ: q1, q2, q3 = X(t1), Y(t2), Z(t3);
+	case .XZY: q1, q2, q3 = X(t1), Z(t2), Y(t3);
+	case .YXZ: q1, q2, q3 = Y(t1), X(t2), Z(t3);
+	case .YZX: q1, q2, q3 = Y(t1), Z(t2), X(t3);
+	case .ZXY: q1, q2, q3 = Z(t1), X(t2), Y(t3);
+	case .ZYX: q1, q2, q3 = Z(t1), Y(t2), X(t3);
+	case .XYX: q1, q2, q3 = X(t1), Y(t2), X(t3);
+	case .XZX: q1, q2, q3 = X(t1), Z(t2), X(t3);
+	case .YXY: q1, q2, q3 = Y(t1), X(t2), Y(t3);
+	case .YZY: q1, q2, q3 = Y(t1), Z(t2), Y(t3);
+	case .ZXZ: q1, q2, q3 = Z(t1), X(t2), Z(t3);
+	case .ZYZ: q1, q2, q3 = Z(t1), Y(t2), Z(t3);
+	}
+
+	return q1 * (q2 * q3);
+}
+
+
+// Quaternionf16s
+
+quaternion_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (q: Quaternionf16) {
+	return quaternion_angle_axis_f16(angle_x, {1, 0, 0});
+}
+quaternion_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (q: Quaternionf16) {
+	return quaternion_angle_axis_f16(angle_y, {0, 1, 0});
+}
+quaternion_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (q: Quaternionf16) {
+	return quaternion_angle_axis_f16(angle_z, {0, 0, 1});
+}
+
+quaternion_from_pitch_yaw_roll_f16 :: proc(pitch, yaw, roll: f16) -> Quaternionf16 {
+	a, b, c := pitch, yaw, roll;
+
+	ca, sa := math.cos(a*0.5), math.sin(a*0.5);
+	cb, sb := math.cos(b*0.5), math.sin(b*0.5);
+	cc, sc := math.cos(c*0.5), math.sin(c*0.5);
+
+	q: Quaternionf16;
+	q.x = sa*cb*cc - ca*sb*sc;
+	q.y = ca*sb*cc + sa*cb*sc;
+	q.z = ca*cb*sc - sa*sb*cc;
+	q.w = ca*cb*cc + sa*sb*sc;
+	return q;
+}
+
+roll_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 {
+	return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z);
+}
+
+pitch_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 {
+	y := 2 * (q.y*q.z + q.w*q.w);
+	x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z;
+
+	if abs(x) <= F16_EPSILON && abs(y) <= F16_EPSILON {
+		return 2 * math.atan2(q.x, q.w);
+	}
+
+	return math.atan2(y, x);
+}
+
+yaw_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 {
+	return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1));
+}
+
+
+pitch_yaw_roll_from_quaternion_f16 :: proc(q: Quaternionf16) -> (pitch, yaw, roll: f16) {
+	pitch = pitch_from_quaternion(q);
+	yaw = yaw_from_quaternion(q);
+	roll = roll_from_quaternion(q);
+	return;
+}
+
+euler_angles_xyz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
+	return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q));
+}
+euler_angles_yxz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
+	return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q));
+}
+euler_angles_xzx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
+	return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q));
+}
+euler_angles_xyx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
+	return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q));
+}
+euler_angles_yxy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
+	return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q));
+}
+euler_angles_yzy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
+	return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q));
+}
+euler_angles_zyz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
+	return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q));
+}
+euler_angles_zxz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
+	return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q));
+}
+euler_angles_xzy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
+	return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q));
+}
+euler_angles_yzx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
+	return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q));
+}
+euler_angles_zyx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
+	return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q));
+}
+euler_angles_zxy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
+	return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q));
+}
+
+
+// Matrix3
+
+
+matrix3_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (m: Matrix3f16) {
+	cos_x, sin_x := math.cos(angle_x), math.sin(angle_x);
+	m[0][0] = 1;
+	m[1][1] = +cos_x;
+	m[2][1] = +sin_x;
+	m[1][2] = -sin_x;
+	m[2][2] = +cos_x;
+	return;
+}
+matrix3_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (m: Matrix3f16) {
+	cos_y, sin_y := math.cos(angle_y), math.sin(angle_y);
+	m[0][0] = +cos_y;
+	m[2][0] = -sin_y;
+	m[1][1] = 1;
+	m[0][2] = +sin_y;
+	m[2][2] = +cos_y;
+	return;
+}
+matrix3_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (m: Matrix3f16) {
+	cos_z, sin_z := math.cos(angle_z), math.sin(angle_z);
+	m[0][0] = +cos_z;
+	m[1][0] = +sin_z;
+	m[1][1] = +cos_z;
+	m[0][1] = -sin_z;
+	m[2][2] = 1;
+	return;
+}
+
+
+matrix3_from_derived_euler_angle_x_f16 :: proc(angle_x: f16, angular_velocity_x: f16) -> (m: Matrix3f16) {
+	cos_x := math.cos(angle_x) * angular_velocity_x;
+	sin_x := math.sin(angle_x) * angular_velocity_x;
+	m[0][0] = 1;
+	m[1][1] = +cos_x;
+	m[2][1] = +sin_x;
+	m[1][2] = -sin_x;
+	m[2][2] = +cos_x;
+	return;
+}
+matrix3_from_derived_euler_angle_y_f16 :: proc(angle_y: f16, angular_velocity_y: f16) -> (m: Matrix3f16) {
+	cos_y := math.cos(angle_y) * angular_velocity_y;
+	sin_y := math.sin(angle_y) * angular_velocity_y;
+	m[0][0] = +cos_y;
+	m[2][0] = -sin_y;
+	m[1][1] = 1;
+	m[0][2] = +sin_y;
+	m[2][2] = +cos_y;
+	return;
+}
+matrix3_from_derived_euler_angle_z_f16 :: proc(angle_z: f16, angular_velocity_z: f16) -> (m: Matrix3f16) {
+	cos_z := math.cos(angle_z) * angular_velocity_z;
+	sin_z := math.sin(angle_z) * angular_velocity_z;
+	m[0][0] = +cos_z;
+	m[1][0] = +sin_z;
+	m[1][1] = +cos_z;
+	m[0][1] = -sin_z;
+	m[2][2] = 1;
+	return;
+}
+
+
+matrix3_from_euler_angles_xy_f16 :: proc(angle_x, angle_y: f16) -> (m: Matrix3f16) {
+	cos_x, sin_x := math.cos(angle_x), math.sin(angle_x);
+	cos_y, sin_y := math.cos(angle_y), math.sin(angle_y);
+	m[0][0] = cos_y;
+	m[1][0] = -sin_x * - sin_y;
+	m[2][0] = -cos_x * - sin_y;
+	m[1][1] = cos_x;
+	m[2][1] = sin_x;
+	m[0][2] = sin_y;
+	m[1][2] = -sin_x * cos_y;
+	m[2][2] = cos_x * cos_y;
+	return;
+}
+
+
+matrix3_from_euler_angles_yx_f16 :: proc(angle_y, angle_x: f16) -> (m: Matrix3f16) {
+	cos_x, sin_x := math.cos(angle_x), math.sin(angle_x);
+	cos_y, sin_y := math.cos(angle_y), math.sin(angle_y);
+	m[0][0] = cos_y;
+	m[2][0] = -sin_y;
+	m[0][1] = sin_y*sin_x;
+	m[1][1] = cos_x;
+	m[2][1] = cos_y*sin_x;
+	m[0][2] = sin_y*cos_x;
+	m[1][2] = -sin_x;
+	m[2][2] = cos_y*cos_x;
+	return;
+}
+
+matrix3_from_euler_angles_xz_f16 :: proc(angle_x, angle_z: f16) -> (m: Matrix3f16) {
+	return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z));
+}
+matrix3_from_euler_angles_zx_f16 :: proc(angle_z, angle_x: f16) -> (m: Matrix3f16) {
+	return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x));
+}
+matrix3_from_euler_angles_yz_f16 :: proc(angle_y, angle_z: f16) -> (m: Matrix3f16) {
+	return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z));
+}
+matrix3_from_euler_angles_zy_f16 :: proc(angle_z, angle_y: f16) -> (m: Matrix3f16) {
+	return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y));
+}
+
+
+matrix3_from_euler_angles_xyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
+	c1 := math.cos(-t1);
+	c2 := math.cos(-t2);
+	c3 := math.cos(-t3);
+	s1 := math.sin(-t1);
+	s2 := math.sin(-t2);
+	s3 := math.sin(-t3);
+
+	m[0][0] = c2 * c3;
+	m[0][1] =-c1 * s3 + s1 * s2 * c3;
+	m[0][2] = s1 * s3 + c1 * s2 * c3;
+	m[1][0] = c2 * s3;
+	m[1][1] = c1 * c3 + s1 * s2 * s3;
+	m[1][2] =-s1 * c3 + c1 * s2 * s3;
+	m[2][0] =-s2;
+	m[2][1] = s1 * c2;
+	m[2][2] = c1 * c2;
+	return;
+}
+
+matrix3_from_euler_angles_yxz_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix3f16) {
+	ch := math.cos(yaw);
+	sh := math.sin(yaw);
+	cp := math.cos(pitch);
+	sp := math.sin(pitch);
+	cb := math.cos(roll);
+	sb := math.sin(roll);
+
+	m[0][0] = ch * cb + sh * sp * sb;
+	m[0][1] = sb * cp;
+	m[0][2] = -sh * cb + ch * sp * sb;
+	m[1][0] = -ch * sb + sh * sp * cb;
+	m[1][1] = cb * cp;
+	m[1][2] = sb * sh + ch * sp * cb;
+	m[2][0] = sh * cp;
+	m[2][1] = -sp;
+	m[2][2] = ch * cp;
+	return;
+}
+
+matrix3_from_euler_angles_xzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c2;
+	m[0][1] = c1 * s2;
+	m[0][2] = s1 * s2;
+	m[1][0] =-c3 * s2;
+	m[1][1] = c1 * c2 * c3 - s1 * s3;
+	m[1][2] = c1 * s3 + c2 * c3 * s1;
+	m[2][0] = s2 * s3;
+	m[2][1] =-c3 * s1 - c1 * c2 * s3;
+	m[2][2] = c1 * c3 - c2 * s1 * s3;
+	return;
+}
+
+matrix3_from_euler_angles_xyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c2;
+	m[0][1] = s1 * s2;
+	m[0][2] =-c1 * s2;
+	m[1][0] = s2 * s3;
+	m[1][1] = c1 * c3 - c2 * s1 * s3;
+	m[1][2] = c3 * s1 + c1 * c2 * s3;
+	m[2][0] = c3 * s2;
+	m[2][1] =-c1 * s3 - c2 * c3 * s1;
+	m[2][2] = c1 * c2 * c3 - s1 * s3;
+	return;
+}
+
+matrix3_from_euler_angles_yxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c1 * c3 - c2 * s1 * s3;
+	m[0][1] = s2* s3;
+	m[0][2] =-c3 * s1 - c1 * c2 * s3;
+	m[1][0] = s1 * s2;
+	m[1][1] = c2;
+	m[1][2] = c1 * s2;
+	m[2][0] = c1 * s3 + c2 * c3 * s1;
+	m[2][1] =-c3 * s2;
+	m[2][2] = c1 * c2 * c3 - s1 * s3;
+	return;
+}
+
+matrix3_from_euler_angles_yzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c1 * c2 * c3 - s1 * s3;
+	m[0][1] = c3 * s2;
+	m[0][2] =-c1 * s3 - c2 * c3 * s1;
+	m[1][0] =-c1 * s2;
+	m[1][1] = c2;
+	m[1][2] = s1 * s2;
+	m[2][0] = c3 * s1 + c1 * c2 * s3;
+	m[2][1] = s2 * s3;
+	m[2][2] = c1 * c3 - c2 * s1 * s3;
+	return;
+}
+
+matrix3_from_euler_angles_zyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c1 * c2 * c3 - s1 * s3;
+	m[0][1] = c1 * s3 + c2 * c3 * s1;
+	m[0][2] =-c3 * s2;
+	m[1][0] =-c3 * s1 - c1 * c2 * s3;
+	m[1][1] = c1 * c3 - c2 * s1 * s3;
+	m[1][2] = s2 * s3;
+	m[2][0] = c1 * s2;
+	m[2][1] = s1 * s2;
+	m[2][2] = c2;
+	return;
+}
+
+matrix3_from_euler_angles_zxz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c1 * c3 - c2 * s1 * s3;
+	m[0][1] = c3 * s1 + c1 * c2 * s3;
+	m[0][2] = s2 *s3;
+	m[1][0] =-c1 * s3 - c2 * c3 * s1;
+	m[1][1] = c1 * c2 * c3 - s1 * s3;
+	m[1][2] = c3 * s2;
+	m[2][0] = s1 * s2;
+	m[2][1] =-c1 * s2;
+	m[2][2] = c2;
+	return;
+}
+
+
+matrix3_from_euler_angles_xzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c2 * c3;
+	m[0][1] = s1 * s3 + c1 * c3 * s2;
+	m[0][2] = c3 * s1 * s2 - c1 * s3;
+	m[1][0] =-s2;
+	m[1][1] = c1 * c2;
+	m[1][2] = c2 * s1;
+	m[2][0] = c2 * s3;
+	m[2][1] = c1 * s2 * s3 - c3 * s1;
+	m[2][2] = c1 * c3 + s1 * s2 *s3;
+	return;
+}
+
+matrix3_from_euler_angles_yzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c1 * c2;
+	m[0][1] = s2;
+	m[0][2] =-c2 * s1;
+	m[1][0] = s1 * s3 - c1 * c3 * s2;
+	m[1][1] = c2 * c3;
+	m[1][2] = c1 * s3 + c3 * s1 * s2;
+	m[2][0] = c3 * s1 + c1 * s2 * s3;
+	m[2][1] =-c2 * s3;
+	m[2][2] = c1 * c3 - s1 * s2 * s3;
+	return;
+}
+
+matrix3_from_euler_angles_zyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c1 * c2;
+	m[0][1] = c2 * s1;
+	m[0][2] =-s2;
+	m[1][0] = c1 * s2 * s3 - c3 * s1;
+	m[1][1] = c1 * c3 + s1 * s2 * s3;
+	m[1][2] = c2 * s3;
+	m[2][0] = s1 * s3 + c1 * c3 * s2;
+	m[2][1] = c3 * s1 * s2 - c1 * s3;
+	m[2][2] = c2 * c3;
+	return;
+}
+
+matrix3_from_euler_angles_zxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c1 * c3 - s1 * s2 * s3;
+	m[0][1] = c3 * s1 + c1 * s2 * s3;
+	m[0][2] =-c2 * s3;
+	m[1][0] =-c2 * s1;
+	m[1][1] = c1 * c2;
+	m[1][2] = s2;
+	m[2][0] = c1 * s3 + c3 * s1 * s2;
+	m[2][1] = s1 * s3 - c1 * c3 * s2;
+	m[2][2] = c2 * c3;
+	return;
+}
+
+
+matrix3_from_yaw_pitch_roll_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix3f16) {
+	ch := math.cos(yaw);
+	sh := math.sin(yaw);
+	cp := math.cos(pitch);
+	sp := math.sin(pitch);
+	cb := math.cos(roll);
+	sb := math.sin(roll);
+
+	m[0][0] = ch * cb + sh * sp * sb;
+	m[0][1] = sb * cp;
+	m[0][2] = -sh * cb + ch * sp * sb;
+	m[1][0] = -ch * sb + sh * sp * cb;
+	m[1][1] = cb * cp;
+	m[1][2] = sb * sh + ch * sp * cb;
+	m[2][0] = sh * cp;
+	m[2][1] = -sp;
+	m[2][2] = ch * cp;
+	return m;
+}
+
+euler_angles_xyz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[2][1], m[2][2]);
+	C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]);
+	T2 := math.atan2(-m[2][0], C2);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]);
+	t1 = -T1;
+	t2 = -T2;
+	t3 = -T3;
+	return;
+}
+
+euler_angles_yxz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[2][0], m[2][2]);
+	C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]);
+	T2 := math.atan2(-m[2][1], C2);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_xzx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[0][2], m[0][1]);
+	S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]);
+	T2 := math.atan2(S2, m[0][0]);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_xyx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[0][1], -m[0][2]);
+	S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]);
+	T2 := math.atan2(S2, m[0][0]);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_yxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[1][0], m[1][2]);
+	S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]);
+	T2 := math.atan2(S2, m[1][1]);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_yzy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[1][2], -m[1][0]);
+	S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]);
+	T2 := math.atan2(S2, m[1][1]);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+euler_angles_zyz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[2][1], m[2][0]);
+	S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]);
+	T2 := math.atan2(S2, m[2][2]);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_zxz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[2][0], -m[2][1]);
+	S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]);
+	T2 := math.atan2(S2, m[2][2]);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_xzy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[1][2], m[1][1]);
+	C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]);
+	T2 := math.atan2(-m[1][0], C2);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_yzx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(-m[0][2], m[0][0]);
+	C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]);
+	T2 := math.atan2(m[0][1], C2);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_zyx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[0][1], m[0][0]);
+	C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]);
+	T2 := math.atan2(-m[0][2], C2);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_zxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(-m[1][0], m[1][1]);
+	C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]);
+	T2 := math.atan2(m[1][2], C2);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+
+// Matrix4
+
+
+matrix4_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (m: Matrix4f16) {
+	cos_x, sin_x := math.cos(angle_x), math.sin(angle_x);
+	m[0][0] = 1;
+	m[1][1] = +cos_x;
+	m[2][1] = +sin_x;
+	m[1][2] = -sin_x;
+	m[2][2] = +cos_x;
+	m[3][3] = 1;
+	return;
+}
+matrix4_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (m: Matrix4f16) {
+	cos_y, sin_y := math.cos(angle_y), math.sin(angle_y);
+	m[0][0] = +cos_y;
+	m[2][0] = -sin_y;
+	m[1][1] = 1;
+	m[0][2] = +sin_y;
+	m[2][2] = +cos_y;
+	m[3][3] = 1;
+	return;
+}
+matrix4_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (m: Matrix4f16) {
+	cos_z, sin_z := math.cos(angle_z), math.sin(angle_z);
+	m[0][0] = +cos_z;
+	m[1][0] = +sin_z;
+	m[1][1] = +cos_z;
+	m[0][1] = -sin_z;
+	m[2][2] = 1;
+	m[3][3] = 1;
+	return;
+}
+
+
+matrix4_from_derived_euler_angle_x_f16 :: proc(angle_x: f16, angular_velocity_x: f16) -> (m: Matrix4f16) {
+	cos_x := math.cos(angle_x) * angular_velocity_x;
+	sin_x := math.sin(angle_x) * angular_velocity_x;
+	m[0][0] = 1;
+	m[1][1] = +cos_x;
+	m[2][1] = +sin_x;
+	m[1][2] = -sin_x;
+	m[2][2] = +cos_x;
+	m[3][3] = 1;
+	return;
+}
+matrix4_from_derived_euler_angle_y_f16 :: proc(angle_y: f16, angular_velocity_y: f16) -> (m: Matrix4f16) {
+	cos_y := math.cos(angle_y) * angular_velocity_y;
+	sin_y := math.sin(angle_y) * angular_velocity_y;
+	m[0][0] = +cos_y;
+	m[2][0] = -sin_y;
+	m[1][1] = 1;
+	m[0][2] = +sin_y;
+	m[2][2] = +cos_y;
+	m[3][3] = 1;
+	return;
+}
+matrix4_from_derived_euler_angle_z_f16 :: proc(angle_z: f16, angular_velocity_z: f16) -> (m: Matrix4f16) {
+	cos_z := math.cos(angle_z) * angular_velocity_z;
+	sin_z := math.sin(angle_z) * angular_velocity_z;
+	m[0][0] = +cos_z;
+	m[1][0] = +sin_z;
+	m[1][1] = +cos_z;
+	m[0][1] = -sin_z;
+	m[2][2] = 1;
+	m[3][3] = 1;
+	return;
+}
+
+
+matrix4_from_euler_angles_xy_f16 :: proc(angle_x, angle_y: f16) -> (m: Matrix4f16) {
+	cos_x, sin_x := math.cos(angle_x), math.sin(angle_x);
+	cos_y, sin_y := math.cos(angle_y), math.sin(angle_y);
+	m[0][0] = cos_y;
+	m[1][0] = -sin_x * - sin_y;
+	m[2][0] = -cos_x * - sin_y;
+	m[1][1] = cos_x;
+	m[2][1] = sin_x;
+	m[0][2] = sin_y;
+	m[1][2] = -sin_x * cos_y;
+	m[2][2] = cos_x * cos_y;
+	m[3][3] = 1;
+	return;
+}
+
+
+matrix4_from_euler_angles_yx_f16 :: proc(angle_y, angle_x: f16) -> (m: Matrix4f16) {
+	cos_x, sin_x := math.cos(angle_x), math.sin(angle_x);
+	cos_y, sin_y := math.cos(angle_y), math.sin(angle_y);
+	m[0][0] = cos_y;
+	m[2][0] = -sin_y;
+	m[0][1] = sin_y*sin_x;
+	m[1][1] = cos_x;
+	m[2][1] = cos_y*sin_x;
+	m[0][2] = sin_y*cos_x;
+	m[1][2] = -sin_x;
+	m[2][2] = cos_y*cos_x;
+	m[3][3] = 1;
+	return;
+}
+
+matrix4_from_euler_angles_xz_f16 :: proc(angle_x, angle_z: f16) -> (m: Matrix4f16) {
+	return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z));
+}
+matrix4_from_euler_angles_zx_f16 :: proc(angle_z, angle_x: f16) -> (m: Matrix4f16) {
+	return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x));
+}
+matrix4_from_euler_angles_yz_f16 :: proc(angle_y, angle_z: f16) -> (m: Matrix4f16) {
+	return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z));
+}
+matrix4_from_euler_angles_zy_f16 :: proc(angle_z, angle_y: f16) -> (m: Matrix4f16) {
+	return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y));
+}
+
+
+matrix4_from_euler_angles_xyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
+	c1 := math.cos(-t1);
+	c2 := math.cos(-t2);
+	c3 := math.cos(-t3);
+	s1 := math.sin(-t1);
+	s2 := math.sin(-t2);
+	s3 := math.sin(-t3);
+
+	m[0][0] = c2 * c3;
+	m[0][1] =-c1 * s3 + s1 * s2 * c3;
+	m[0][2] = s1 * s3 + c1 * s2 * c3;
+	m[0][3] = 0;
+	m[1][0] = c2 * s3;
+	m[1][1] = c1 * c3 + s1 * s2 * s3;
+	m[1][2] =-s1 * c3 + c1 * s2 * s3;
+	m[1][3] = 0;
+	m[2][0] =-s2;
+	m[2][1] = s1 * c2;
+	m[2][2] = c1 * c2;
+	m[2][3] = 0;
+	m[3][0] = 0;
+	m[3][1] = 0;
+	m[3][2] = 0;
+	m[3][3] = 1;
+	return;
+}
+
+matrix4_from_euler_angles_yxz_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix4f16) {
+	ch := math.cos(yaw);
+	sh := math.sin(yaw);
+	cp := math.cos(pitch);
+	sp := math.sin(pitch);
+	cb := math.cos(roll);
+	sb := math.sin(roll);
+
+	m[0][0] = ch * cb + sh * sp * sb;
+	m[0][1] = sb * cp;
+	m[0][2] = -sh * cb + ch * sp * sb;
+	m[0][3] = 0;
+	m[1][0] = -ch * sb + sh * sp * cb;
+	m[1][1] = cb * cp;
+	m[1][2] = sb * sh + ch * sp * cb;
+	m[1][3] = 0;
+	m[2][0] = sh * cp;
+	m[2][1] = -sp;
+	m[2][2] = ch * cp;
+	m[2][3] = 0;
+	m[3][0] = 0;
+	m[3][1] = 0;
+	m[3][2] = 0;
+	m[3][3] = 1;
+	return;
+}
+
+matrix4_from_euler_angles_xzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c2;
+	m[0][1] = c1 * s2;
+	m[0][2] = s1 * s2;
+	m[0][3] = 0;
+	m[1][0] =-c3 * s2;
+	m[1][1] = c1 * c2 * c3 - s1 * s3;
+	m[1][2] = c1 * s3 + c2 * c3 * s1;
+	m[1][3] = 0;
+	m[2][0] = s2 * s3;
+	m[2][1] =-c3 * s1 - c1 * c2 * s3;
+	m[2][2] = c1 * c3 - c2 * s1 * s3;
+	m[2][3] = 0;
+	m[3][0] = 0;
+	m[3][1] = 0;
+	m[3][2] = 0;
+	m[3][3] = 1;
+	return;
+}
+
+matrix4_from_euler_angles_xyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c2;
+	m[0][1] = s1 * s2;
+	m[0][2] =-c1 * s2;
+	m[0][3] = 0;
+	m[1][0] = s2 * s3;
+	m[1][1] = c1 * c3 - c2 * s1 * s3;
+	m[1][2] = c3 * s1 + c1 * c2 * s3;
+	m[1][3] = 0;
+	m[2][0] = c3 * s2;
+	m[2][1] =-c1 * s3 - c2 * c3 * s1;
+	m[2][2] = c1 * c2 * c3 - s1 * s3;
+	m[2][3] = 0;
+	m[3][0] = 0;
+	m[3][1] = 0;
+	m[3][2] = 0;
+	m[3][3] = 1;
+	return;
+}
+
+matrix4_from_euler_angles_yxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c1 * c3 - c2 * s1 * s3;
+	m[0][1] = s2* s3;
+	m[0][2] =-c3 * s1 - c1 * c2 * s3;
+	m[0][3] = 0;
+	m[1][0] = s1 * s2;
+	m[1][1] = c2;
+	m[1][2] = c1 * s2;
+	m[1][3] = 0;
+	m[2][0] = c1 * s3 + c2 * c3 * s1;
+	m[2][1] =-c3 * s2;
+	m[2][2] = c1 * c2 * c3 - s1 * s3;
+	m[2][3] = 0;
+	m[3][0] = 0;
+	m[3][1] = 0;
+	m[3][2] = 0;
+	m[3][3] = 1;
+	return;
+}
+
+matrix4_from_euler_angles_yzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c1 * c2 * c3 - s1 * s3;
+	m[0][1] = c3 * s2;
+	m[0][2] =-c1 * s3 - c2 * c3 * s1;
+	m[0][3] = 0;
+	m[1][0] =-c1 * s2;
+	m[1][1] = c2;
+	m[1][2] = s1 * s2;
+	m[1][3] = 0;
+	m[2][0] = c3 * s1 + c1 * c2 * s3;
+	m[2][1] = s2 * s3;
+	m[2][2] = c1 * c3 - c2 * s1 * s3;
+	m[2][3] = 0;
+	m[3][0] = 0;
+	m[3][1] = 0;
+	m[3][2] = 0;
+	m[3][3] = 1;
+	return;
+}
+
+matrix4_from_euler_angles_zyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c1 * c2 * c3 - s1 * s3;
+	m[0][1] = c1 * s3 + c2 * c3 * s1;
+	m[0][2] =-c3 * s2;
+	m[0][3] = 0;
+	m[1][0] =-c3 * s1 - c1 * c2 * s3;
+	m[1][1] = c1 * c3 - c2 * s1 * s3;
+	m[1][2] = s2 * s3;
+	m[1][3] = 0;
+	m[2][0] = c1 * s2;
+	m[2][1] = s1 * s2;
+	m[2][2] = c2;
+	m[2][3] = 0;
+	m[3][0] = 0;
+	m[3][1] = 0;
+	m[3][2] = 0;
+	m[3][3] = 1;
+	return;
+}
+
+matrix4_from_euler_angles_zxz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c1 * c3 - c2 * s1 * s3;
+	m[0][1] = c3 * s1 + c1 * c2 * s3;
+	m[0][2] = s2 *s3;
+	m[0][3] = 0;
+	m[1][0] =-c1 * s3 - c2 * c3 * s1;
+	m[1][1] = c1 * c2 * c3 - s1 * s3;
+	m[1][2] = c3 * s2;
+	m[1][3] = 0;
+	m[2][0] = s1 * s2;
+	m[2][1] =-c1 * s2;
+	m[2][2] = c2;
+	m[2][3] = 0;
+	m[3][0] = 0;
+	m[3][1] = 0;
+	m[3][2] = 0;
+	m[3][3] = 1;
+	return;
+}
+
+
+matrix4_from_euler_angles_xzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c2 * c3;
+	m[0][1] = s1 * s3 + c1 * c3 * s2;
+	m[0][2] = c3 * s1 * s2 - c1 * s3;
+	m[0][3] = 0;
+	m[1][0] =-s2;
+	m[1][1] = c1 * c2;
+	m[1][2] = c2 * s1;
+	m[1][3] = 0;
+	m[2][0] = c2 * s3;
+	m[2][1] = c1 * s2 * s3 - c3 * s1;
+	m[2][2] = c1 * c3 + s1 * s2 *s3;
+	m[2][3] = 0;
+	m[3][0] = 0;
+	m[3][1] = 0;
+	m[3][2] = 0;
+	m[3][3] = 1;
+	return;
+}
+
+matrix4_from_euler_angles_yzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c1 * c2;
+	m[0][1] = s2;
+	m[0][2] =-c2 * s1;
+	m[0][3] = 0;
+	m[1][0] = s1 * s3 - c1 * c3 * s2;
+	m[1][1] = c2 * c3;
+	m[1][2] = c1 * s3 + c3 * s1 * s2;
+	m[1][3] = 0;
+	m[2][0] = c3 * s1 + c1 * s2 * s3;
+	m[2][1] =-c2 * s3;
+	m[2][2] = c1 * c3 - s1 * s2 * s3;
+	m[2][3] = 0;
+	m[3][0] = 0;
+	m[3][1] = 0;
+	m[3][2] = 0;
+	m[3][3] = 1;
+	return;
+}
+
+matrix4_from_euler_angles_zyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c1 * c2;
+	m[0][1] = c2 * s1;
+	m[0][2] =-s2;
+	m[0][3] = 0;
+	m[1][0] = c1 * s2 * s3 - c3 * s1;
+	m[1][1] = c1 * c3 + s1 * s2 * s3;
+	m[1][2] = c2 * s3;
+	m[1][3] = 0;
+	m[2][0] = s1 * s3 + c1 * c3 * s2;
+	m[2][1] = c3 * s1 * s2 - c1 * s3;
+	m[2][2] = c2 * c3;
+	m[2][3] = 0;
+	m[3][0] = 0;
+	m[3][1] = 0;
+	m[3][2] = 0;
+	m[3][3] = 1;
+	return;
+}
+
+matrix4_from_euler_angles_zxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
+	c1 := math.cos(t1);
+	s1 := math.sin(t1);
+	c2 := math.cos(t2);
+	s2 := math.sin(t2);
+	c3 := math.cos(t3);
+	s3 := math.sin(t3);
+
+	m[0][0] = c1 * c3 - s1 * s2 * s3;
+	m[0][1] = c3 * s1 + c1 * s2 * s3;
+	m[0][2] =-c2 * s3;
+	m[0][3] = 0;
+	m[1][0] =-c2 * s1;
+	m[1][1] = c1 * c2;
+	m[1][2] = s2;
+	m[1][3] = 0;
+	m[2][0] = c1 * s3 + c3 * s1 * s2;
+	m[2][1] = s1 * s3 - c1 * c3 * s2;
+	m[2][2] = c2 * c3;
+	m[2][3] = 0;
+	m[3][0] = 0;
+	m[3][1] = 0;
+	m[3][2] = 0;
+	m[3][3] = 1;
+	return;
+}
+
+
+matrix4_from_yaw_pitch_roll_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix4f16) {
+	ch := math.cos(yaw);
+	sh := math.sin(yaw);
+	cp := math.cos(pitch);
+	sp := math.sin(pitch);
+	cb := math.cos(roll);
+	sb := math.sin(roll);
+
+	m[0][0] = ch * cb + sh * sp * sb;
+	m[0][1] = sb * cp;
+	m[0][2] = -sh * cb + ch * sp * sb;
+	m[0][3] = 0;
+	m[1][0] = -ch * sb + sh * sp * cb;
+	m[1][1] = cb * cp;
+	m[1][2] = sb * sh + ch * sp * cb;
+	m[1][3] = 0;
+	m[2][0] = sh * cp;
+	m[2][1] = -sp;
+	m[2][2] = ch * cp;
+	m[2][3] = 0;
+	m[3][0] = 0;
+	m[3][1] = 0;
+	m[3][2] = 0;
+	m[3][3] = 1;
+	return m;
+}
+
+euler_angles_xyz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[2][1], m[2][2]);
+	C2 := math.sqrt(m[0][0]*m[0][0] + m[1][0]*m[1][0]);
+	T2 := math.atan2(-m[2][0], C2);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(S1*m[0][2] - C1*m[0][1], C1*m[1][1] - S1*m[1][2]);
+	t1 = -T1;
+	t2 = -T2;
+	t3 = -T3;
+	return;
+}
+
+euler_angles_yxz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[2][0], m[2][2]);
+	C2 := math.sqrt(m[0][1]*m[0][1] + m[1][1]*m[1][1]);
+	T2 := math.atan2(-m[2][1], C2);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(S1*m[1][2] - C1*m[1][0], C1*m[0][0] - S1*m[0][2]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_xzx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[0][2], m[0][1]);
+	S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]);
+	T2 := math.atan2(S2, m[0][0]);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(C1*m[1][2] - S1*m[1][1], C1*m[2][2] - S1*m[2][1]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_xyx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[0][1], -m[0][2]);
+	S2 := math.sqrt(m[1][0]*m[1][0] + m[2][0]*m[2][0]);
+	T2 := math.atan2(S2, m[0][0]);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(-C1*m[2][1] - S1*m[2][2], C1*m[1][1] + S1*m[1][2]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_yxy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[1][0], m[1][2]);
+	S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]);
+	T2 := math.atan2(S2, m[1][1]);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(C1*m[2][0] - S1*m[2][2], C1*m[0][0] - S1*m[0][2]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_yzy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[1][2], -m[1][0]);
+	S2 := math.sqrt(m[0][1]*m[0][1] + m[2][1]*m[2][1]);
+	T2 := math.atan2(S2, m[1][1]);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(-S1*m[0][0] - C1*m[0][2], S1*m[2][0] + C1*m[2][2]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+euler_angles_zyz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[2][1], m[2][0]);
+	S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]);
+	T2 := math.atan2(S2, m[2][2]);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(C1*m[0][1] - S1*m[0][0], C1*m[1][1] - S1*m[1][0]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_zxz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[2][0], -m[2][1]);
+	S2 := math.sqrt(m[0][2]*m[0][2] + m[1][2]*m[1][2]);
+	T2 := math.atan2(S2, m[2][2]);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(-C1*m[1][0] - S1*m[1][1], C1*m[0][0] + S1*m[0][1]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_xzy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[1][2], m[1][1]);
+	C2 := math.sqrt(m[0][0]*m[0][0] + m[2][0]*m[2][0]);
+	T2 := math.atan2(-m[1][0], C2);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(S1*m[0][1] - C1*m[0][2], C1*m[2][2] - S1*m[2][1]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_yzx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(-m[0][2], m[0][0]);
+	C2 := math.sqrt(m[1][1]*m[1][1] + m[2][1]*m[2][1]);
+	T2 := math.atan2(m[0][1], C2);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(S1*m[1][0] + C1*m[1][2], S1*m[2][0] + C1*m[2][2]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_zyx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(m[0][1], m[0][0]);
+	C2 := math.sqrt(m[1][2]*m[1][2] + m[2][2]*m[2][2]);
+	T2 := math.atan2(-m[0][2], C2);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(S1*m[2][0] - C1*m[2][1], C1*m[1][1] - S1*m[1][0]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}
+
+euler_angles_zxy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
+	T1 := math.atan2(-m[1][0], m[1][1]);
+	C2 := math.sqrt(m[0][2]*m[0][2] + m[2][2]*m[2][2]);
+	T2 := math.atan2(m[1][2], C2);
+	S1 := math.sin(T1);
+	C1 := math.cos(T1);
+	T3 := math.atan2(C1*m[2][0] + S1*m[2][1], C1*m[0][0] + S1*m[0][1]);
+	t1 = T1;
+	t2 = T2;
+	t3 = T3;
+	return;
+}

Some files were not shown because too many files changed in this diff