-module(matrix@mat3f). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/matrix/mat3f.gleam"). -export([new/9, from_cols/3, from_diagonal/1, from_quaternion/1, transpose/1, determinant/1, mul_vec3/2, mul_transpose_vec3/2, negate/1, add/2, subtract/2, multiply/2, scale/2, scale_diagonal/2, inverse/1, divide/2]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. ?MODULEDOC(" 3x3 matrices of floats\n"). -file("src/matrix/mat3f.gleam", 33). ?DOC( " Constructs a `Mat3f` from its components:\n" " ```text\n" " | a d g |\n" " | b e h |\n" " | c f i |\n" " ```\n" ). -spec new( float(), float(), float(), float(), float(), float(), float(), float(), float() ) -> vec@vec3:vec3(vec@vec3:vec3(float())). new(A, B, C, D, E, F, G, H, I) -> {vec3, {vec3, A, B, C}, {vec3, D, E, F}, {vec3, G, H, I}}. -file("src/matrix/mat3f.gleam", 53). ?DOC( " Constructs a `Mat3f` from its three columns.\n" " ```text\n" " | ax bx cx |\n" " | ay by cy |\n" " | az bz cz |\n" " ```\n" ). -spec from_cols( vec@vec3:vec3(float()), vec@vec3:vec3(float()), vec@vec3:vec3(float()) ) -> vec@vec3:vec3(vec@vec3:vec3(float())). from_cols(A, B, C) -> {vec3, A, B, C}. -file("src/matrix/mat3f.gleam", 63). ?DOC( " Constructs a `Mat3f` with the given diagonal and all other entries set to 0.\n" " ```text\n" " | x 0.0 0.0 |\n" " | 0.0 y 0.0 |\n" " | 0.0 0.0 z |\n" " ```\n" ). -spec from_diagonal(vec@vec3:vec3(float())) -> vec@vec3:vec3(vec@vec3:vec3(float())). from_diagonal(Diag) -> new( erlang:element(2, Diag), +0.0, +0.0, +0.0, erlang:element(3, Diag), +0.0, +0.0, +0.0, erlang:element(4, Diag) ). -file("src/matrix/mat3f.gleam", 68). ?DOC(" Constructs a 3D rotation matrix from the given quaternion, represented as a `vec4.Vec4(Float)`.\n"). -spec from_quaternion(vec@vec4:vec4(float())) -> vec@vec3:vec3(vec@vec3:vec3(float())). from_quaternion(Q) -> Rotation = vec@vec4f:normalize(Q), X2 = erlang:element(2, Rotation) + erlang:element(2, Rotation), Y2 = erlang:element(3, Rotation) + erlang:element(3, Rotation), Z2 = erlang:element(4, Rotation) + erlang:element(4, Rotation), Xx = erlang:element(2, Rotation) * X2, Xy = erlang:element(2, Rotation) * Y2, Xz = erlang:element(2, Rotation) * Z2, Yy = erlang:element(3, Rotation) * Y2, Yz = erlang:element(3, Rotation) * Z2, Zz = erlang:element(4, Rotation) * Z2, Wx = erlang:element(5, Rotation) * X2, Wy = erlang:element(5, Rotation) * Y2, Wz = erlang:element(5, Rotation) * Z2, from_cols( {vec3, 1.0 - (Yy + Zz), Xy + Wz, Xz - Wy}, {vec3, Xy - Wz, 1.0 - (Xx + Zz), Yz + Wx}, {vec3, Xz + Wy, Yz - Wx, 1.0 - (Xx + Yy)} ). -file("src/matrix/mat3f.gleam", 92). ?DOC(" Transposes the `Mat3f` along the diagonal.\n"). -spec transpose(vec@vec3:vec3(vec@vec3:vec3(float()))) -> vec@vec3:vec3(vec@vec3:vec3(float())). transpose(Mat) -> new( erlang:element(2, erlang:element(2, Mat)), erlang:element(2, erlang:element(3, Mat)), erlang:element(2, erlang:element(4, Mat)), erlang:element(3, erlang:element(2, Mat)), erlang:element(3, erlang:element(3, Mat)), erlang:element(3, erlang:element(4, Mat)), erlang:element(4, erlang:element(2, Mat)), erlang:element(4, erlang:element(3, Mat)), erlang:element(4, erlang:element(4, Mat)) ). -file("src/matrix/mat3f.gleam", 107). ?DOC(" Returns the determinant for the `Mat3f`.\n"). -spec determinant(vec@vec3:vec3(vec@vec3:vec3(float()))) -> float(). determinant(Mat) -> {vec3, {vec3, A1, B1, C1}, {vec3, A2, B2, C2}, {vec3, A3, B3, C3}} = Mat, ((((((A1 * B2) * C3) - ((A1 * B3) * C2)) - ((A2 * B1) * C3)) + ((A2 * B3) * C1)) + ((A3 * B1) * C2)) - ((A3 * B2) * C1). -file("src/matrix/mat3f.gleam", 143). ?DOC(" Transforms a `Vec3f` by this `Mat3f`.\n"). -spec mul_vec3(vec@vec3:vec3(vec@vec3:vec3(float())), vec@vec3:vec3(float())) -> vec@vec3:vec3(float()). mul_vec3(Mat, Rhs) -> _pipe = vec@vec3:map2(Mat, Rhs, fun vec@vec3f:scale/2), _pipe@1 = vec@vec3:to_list(_pipe), vec@vec3f:sum(_pipe@1). -file("src/matrix/mat3f.gleam", 150). ?DOC(" Transforms a `Vec3f` by the transpose of this `Mat3f`.\n"). -spec mul_transpose_vec3( vec@vec3:vec3(vec@vec3:vec3(float())), vec@vec3:vec3(float()) ) -> vec@vec3:vec3(float()). mul_transpose_vec3(Mat, Rhs) -> vec@vec3:map(Mat, fun(_capture) -> vec@vec3f:dot(_capture, Rhs) end). -file("src/matrix/mat3f.gleam", 155). ?DOC(" Negates all elements of the `Mat3f`\n"). -spec negate(vec@vec3:vec3(vec@vec3:vec3(float()))) -> vec@vec3:vec3(vec@vec3:vec3(float())). negate(Mat) -> vec@vec3:map(Mat, fun vec@vec3f:negate/1). -file("src/matrix/mat3f.gleam", 160). ?DOC(" Adds two `Mat3f` together.\n"). -spec add( vec@vec3:vec3(vec@vec3:vec3(float())), vec@vec3:vec3(vec@vec3:vec3(float())) ) -> vec@vec3:vec3(vec@vec3:vec3(float())). add(A, B) -> vec@vec3:map2(A, B, fun vec@vec3f:add/2). -file("src/matrix/mat3f.gleam", 165). ?DOC(" Subtracts one `Mat3f` from the other.\n"). -spec subtract( vec@vec3:vec3(vec@vec3:vec3(float())), vec@vec3:vec3(vec@vec3:vec3(float())) ) -> vec@vec3:vec3(vec@vec3:vec3(float())). subtract(A, B) -> vec@vec3:map2(A, B, fun vec@vec3f:subtract/2). -file("src/matrix/mat3f.gleam", 170). ?DOC(" Multiplies two `Mat3f` together.\n"). -spec multiply( vec@vec3:vec3(vec@vec3:vec3(float())), vec@vec3:vec3(vec@vec3:vec3(float())) ) -> vec@vec3:vec3(vec@vec3:vec3(float())). multiply(A, B) -> vec@vec3:map(B, fun(_capture) -> mul_vec3(A, _capture) end). -file("src/matrix/mat3f.gleam", 181). ?DOC(" Scales the `Mat3f` by a `Float` factor.\n"). -spec scale(vec@vec3:vec3(vec@vec3:vec3(float())), float()) -> vec@vec3:vec3(vec@vec3:vec3(float())). scale(Mat, Scale) -> vec@vec3:map(Mat, fun(_capture) -> vec@vec3f:scale(_capture, Scale) end). -file("src/matrix/mat3f.gleam", 188). ?DOC( " Scales the `Mat3f` by a `Vec3f`.\n" "\n" " This is faster than creating a diagonal scaling matrix and then multiplying that.\n" ). -spec scale_diagonal( vec@vec3:vec3(vec@vec3:vec3(float())), vec@vec3:vec3(float()) ) -> vec@vec3:vec3(vec@vec3:vec3(float())). scale_diagonal(Mat, Scale) -> vec@vec3:map2(Mat, Scale, fun vec@vec3f:scale/2). -file("src/matrix/mat3f.gleam", 192). -spec xz_(vec@vec3:vec3(IRO)) -> vec@vec2:vec2(IRO). xz_(V) -> {vec2, erlang:element(2, V), erlang:element(4, V)}. -file("src/matrix/mat3f.gleam", 196). -spec xy_(vec@vec3:vec3(IRR)) -> vec@vec2:vec2(IRR). xy_(V) -> {vec2, erlang:element(2, V), erlang:element(3, V)}. -file("src/matrix/mat3f.gleam", 200). -spec yz_(vec@vec3:vec3(IRU)) -> vec@vec2:vec2(IRU). yz_(V) -> {vec2, erlang:element(3, V), erlang:element(4, V)}. -file("src/matrix/mat3f.gleam", 118). ?DOC(" Inverts the `Mat3f`, returning an error if the determinant is zero.\n"). -spec inverse(vec@vec3:vec3(vec@vec3:vec3(float()))) -> {ok, vec@vec3:vec3(vec@vec3:vec3(float()))} | {error, nil}. inverse(Mat) -> gleam@result:map( gleam@float:divide(1.0, determinant(Mat)), fun(Inv_det) -> Xx = begin _pipe = Mat, _pipe@1 = yz_(_pipe), _pipe@2 = vec@vec2:map(_pipe@1, fun yz_/1), matrix@mat2f:determinant(_pipe@2) end, Xy = begin _pipe@3 = Mat, _pipe@4 = xz_(_pipe@3), _pipe@5 = vec@vec2:map(_pipe@4, fun yz_/1), _pipe@6 = vec@vec2:swap(_pipe@5), matrix@mat2f:determinant(_pipe@6) end, Xz = begin _pipe@7 = Mat, _pipe@8 = xy_(_pipe@7), _pipe@9 = vec@vec2:map(_pipe@8, fun yz_/1), matrix@mat2f:determinant(_pipe@9) end, Yx = begin _pipe@10 = Mat, _pipe@11 = yz_(_pipe@10), _pipe@12 = vec@vec2:map(_pipe@11, fun xz_/1), _pipe@13 = vec@vec2:swap(_pipe@12), matrix@mat2f:determinant(_pipe@13) end, Yy = begin _pipe@14 = Mat, _pipe@15 = xz_(_pipe@14), _pipe@16 = vec@vec2:map(_pipe@15, fun xz_/1), matrix@mat2f:determinant(_pipe@16) end, Yz = begin _pipe@17 = Mat, _pipe@18 = xy_(_pipe@17), _pipe@19 = vec@vec2:map(_pipe@18, fun xz_/1), _pipe@20 = vec@vec2:swap(_pipe@19), matrix@mat2f:determinant(_pipe@20) end, Zx = begin _pipe@21 = Mat, _pipe@22 = yz_(_pipe@21), _pipe@23 = vec@vec2:map(_pipe@22, fun xy_/1), matrix@mat2f:determinant(_pipe@23) end, Zy = begin _pipe@24 = Mat, _pipe@25 = xz_(_pipe@24), _pipe@26 = vec@vec2:map(_pipe@25, fun xy_/1), _pipe@27 = vec@vec2:swap(_pipe@26), matrix@mat2f:determinant(_pipe@27) end, Zz = begin _pipe@28 = Mat, _pipe@29 = xy_(_pipe@28), _pipe@30 = vec@vec2:map(_pipe@29, fun xy_/1), matrix@mat2f:determinant(_pipe@30) end, scale(new(Xx, Xy, Xz, Yx, Yy, Yz, Zx, Zy, Zz), Inv_det) end ). -file("src/matrix/mat3f.gleam", 175). ?DOC(" Divides one `Mat3f` by another. Equivalent to multiplying the inverse of the second matrix.\n"). -spec divide( vec@vec3:vec3(vec@vec3:vec3(float())), vec@vec3:vec3(vec@vec3:vec3(float())) ) -> {ok, vec@vec3:vec3(vec@vec3:vec3(float()))} | {error, nil}. divide(A, B) -> gleam@result:map(inverse(B), fun(Inv_b) -> multiply(A, Inv_b) end).