Current section

Files

Jump to
matrix_gleam src matrix@mat3f.erl
Raw

src/matrix@mat3f.erl

-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, from_axis_angle/2, from_rotation_x/1, from_rotation_y/1, from_rotation_z/1, from_translation/1, from_angle/1, from_scale_angle_translation/3, from_scale/1, transpose/1, determinant/1, mul_vec3/2, transform_point2/2, transform_vector2/2, look_to_rh/2, look_to_lh/2, look_at_lh/3, look_at_rh/3, mul_transpose_vec3/2, negate/1, absolute_value/1, add/2, subtract/2, multiply/2, scale/2, inverse/1, divide/2, scale_diagonal/2, reciprocal/1, sum/1, product/1]).
-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", 31).
?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", 51).
?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", 61).
?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", 66).
?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", 90).
?DOC(" Creates a 3D rotation matrix from a normalized rotation `axis` and `angle` (in radians).\n").
-spec from_axis_angle(vec@vec3:vec3(float()), float()) -> vec@vec3:vec3(vec@vec3:vec3(float())).
from_axis_angle(Axis, Angle) ->
Axis@1 = vec@vec3f:normalize(Axis),
Sin_a = gleam_community@maths:sin(Angle),
Cos_a = gleam_community@maths:cos(Angle),
{vec3, X, Y, Z} = Axis@1,
{vec3, Xsin, Ysin, Zsin} = vec@vec3f:scale(Axis@1, Sin_a),
{vec3, X2, Y2, Z2} = vec@vec3f:multiply(Axis@1, Axis@1),
Omc = 1.0 - Cos_a,
Xyomc = (X * Y) * Omc,
Xzomc = (X * Z) * Omc,
Yzomc = (Y * Z) * Omc,
from_cols(
{vec3, (X2 * Omc) + Cos_a, Xyomc + Zsin, Yzomc - Ysin},
{vec3, Xyomc - Zsin, (Y2 * Omc) + Cos_a, Yzomc + Xsin},
{vec3, Xzomc + Ysin, Yzomc - Xsin, (Z2 * Omc) + Cos_a}
).
-file("src/matrix/mat3f.gleam", 109).
?DOC(" Creates a 3D rotation matrix from `angle` in radians around the x axis.\n").
-spec from_rotation_x(float()) -> vec@vec3:vec3(vec@vec3:vec3(float())).
from_rotation_x(Angle) ->
Sina = gleam_community@maths:sin(Angle),
Cosa = gleam_community@maths:cos(Angle),
from_cols(
{vec3, 1.0, +0.0, +0.0},
{vec3, +0.0, Cosa, Sina},
{vec3, +0.0, +0.0 - Sina, Cosa}
).
-file("src/matrix/mat3f.gleam", 116).
?DOC(" Creates a 3D rotation matrix from `angle` in radians around the y axis.\n").
-spec from_rotation_y(float()) -> vec@vec3:vec3(vec@vec3:vec3(float())).
from_rotation_y(Angle) ->
Sina = gleam_community@maths:sin(Angle),
Cosa = gleam_community@maths:cos(Angle),
from_cols(
{vec3, Cosa, +0.0, +0.0 - Sina},
{vec3, +0.0, 1.0, +0.0},
{vec3, Sina, +0.0, Cosa}
).
-file("src/matrix/mat3f.gleam", 123).
?DOC(" Creates a 3D rotation matrix from `angle` in radians around the z axis.\n").
-spec from_rotation_z(float()) -> vec@vec3:vec3(vec@vec3:vec3(float())).
from_rotation_z(Angle) ->
Sina = gleam_community@maths:sin(Angle),
Cosa = gleam_community@maths:cos(Angle),
from_cols(
{vec3, Cosa, Sina, +0.0},
{vec3, +0.0 - Sina, Cosa, +0.0},
{vec3, +0.0, +0.0, 1.0}
).
-file("src/matrix/mat3f.gleam", 132).
?DOC(
" Creates an affine transformation matrix from the given 2D `translation`.\n"
"\n"
" The resulting matrix can be used to transform 2D points and vectors.\n"
).
-spec from_translation(vec@vec2:vec2(float())) -> vec@vec3:vec3(vec@vec3:vec3(float())).
from_translation(Translation) ->
from_cols(
{vec3, 1.0, +0.0, +0.0},
{vec3, +0.0, 1.0, +0.0},
matrix@internal@projection:extend2(Translation, 1.0)
).
-file("src/matrix/mat3f.gleam", 139).
?DOC(
" Creates an affine transformation matrix from the given 2D rotation `angle` (in radians).\n"
"\n"
" The resulting matrix can be used to transform 2D points and vectors.\n"
).
-spec from_angle(float()) -> vec@vec3:vec3(vec@vec3:vec3(float())).
from_angle(Angle) ->
from_rotation_z(Angle).
-file("src/matrix/mat3f.gleam", 146).
?DOC(
" Creates an affine transformation matrix from the given 2D `scale`, rotation `angle` (in radians), and `translation`.\n"
"\n"
" The resulting matrix can be used to transform 2D points and vectors.\n"
).
-spec from_scale_angle_translation(
vec@vec2:vec2(float()),
float(),
vec@vec2:vec2(float())
) -> vec@vec3:vec3(vec@vec3:vec3(float())).
from_scale_angle_translation(Scale, Angle, Translation) ->
Sina = gleam_community@maths:sin(Angle),
Cosa = gleam_community@maths:cos(Angle),
from_cols(
{vec3,
Cosa * erlang:element(2, Scale),
Sina * erlang:element(2, Scale),
+0.0},
{vec3,
gleam@float:negate(Sina) * erlang:element(3, Scale),
Cosa * erlang:element(3, Scale),
+0.0},
matrix@internal@projection:extend2(Translation, 1.0)
).
-file("src/matrix/mat3f.gleam", 163).
?DOC(
" Creates an affine transformation matrix from teh given non-uniform 2D `scale`.\n"
"\n"
" The resulting matrix can be used to transform 2D points and vectors.\n"
).
-spec from_scale(vec@vec2:vec2(float())) -> vec@vec3:vec3(vec@vec3:vec3(float())).
from_scale(Scale) ->
from_diagonal(matrix@internal@projection:extend2(Scale, 1.0)).
-file("src/matrix/mat3f.gleam", 168).
?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", 183).
?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", 219).
?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", 230).
?DOC(
" Transforms the given 2D vector as a point.\n"
"\n"
" This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `1`.\n"
"\n"
" This function assumes that `mat` contains a valid affine transform.\n"
).
-spec transform_point2(
vec@vec3:vec3(vec@vec3:vec3(float())),
vec@vec2:vec2(float())
) -> vec@vec2:vec2(float()).
transform_point2(Mat, Rhs) ->
_pipe = matrix@mat2f:from_cols(
matrix@internal@projection:to_xy(erlang:element(2, Mat)),
matrix@internal@projection:to_xy(erlang:element(3, Mat))
),
_pipe@1 = matrix@mat2f:mul_transpose_vec2(_pipe, Rhs),
vec@vec2f:add(
_pipe@1,
matrix@internal@projection:to_xy(erlang:element(4, Mat))
).
-file("src/matrix/mat3f.gleam", 239).
?DOC(
" Rotates the given 2D vector.\n"
"\n"
" This is the equivalent of multiplying `rhs` as a 3D vector where `z` is `0`.\n"
).
-spec transform_vector2(
vec@vec3:vec3(vec@vec3:vec3(float())),
vec@vec2:vec2(float())
) -> vec@vec2:vec2(float()).
transform_vector2(Mat, Rhs) ->
_pipe = matrix@mat2f:from_cols(
matrix@internal@projection:to_xy(erlang:element(2, Mat)),
matrix@internal@projection:to_xy(erlang:element(3, Mat))
),
matrix@mat2f:mul_transpose_vec2(_pipe, Rhs).
-file("src/matrix/mat3f.gleam", 254).
?DOC(
" Creates a right-handed view matrix using a facing direction and an up direction.\n"
"\n"
" For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.\n"
).
-spec look_to_rh(vec@vec3:vec3(float()), vec@vec3:vec3(float())) -> vec@vec3:vec3(vec@vec3:vec3(float())).
look_to_rh(Dir, Up) ->
Up@1 = vec@vec3f:normalize(Up),
F = vec@vec3f:normalize(Dir),
S = begin
_pipe = F,
_pipe@1 = vec@vec3f:cross(_pipe, Up@1),
vec@vec3f:normalize(_pipe@1)
end,
U = vec@vec3f:cross(S, F),
Neg_f = vec@vec3f:negate(F),
from_cols(
{vec3,
erlang:element(2, S),
erlang:element(2, U),
erlang:element(2, Neg_f)},
{vec3,
erlang:element(3, S),
erlang:element(3, U),
erlang:element(3, Neg_f)},
{vec3,
erlang:element(4, S),
erlang:element(4, U),
erlang:element(4, Neg_f)}
).
-file("src/matrix/mat3f.gleam", 247).
?DOC(
" Creates a left-handed view matrix using a facing direction and an up direction.\n"
"\n"
" For a view coordinate system with `+X=right`, `+Y=up`, and `+Z=forward`.\n"
).
-spec look_to_lh(vec@vec3:vec3(float()), vec@vec3:vec3(float())) -> vec@vec3:vec3(vec@vec3:vec3(float())).
look_to_lh(Dir, Up) ->
look_to_rh(vec@vec3f:negate(Dir), Up).
-file("src/matrix/mat3f.gleam", 272).
?DOC(
" Creates a left-handed view matrix using a camera position, a focal point and an up\n"
" direction.\n"
"\n"
" For a view coordinate system with `+X=right`, `+Y=up` and `+Z=forward`.\n"
).
-spec look_at_lh(
vec@vec3:vec3(float()),
vec@vec3:vec3(float()),
vec@vec3:vec3(float())
) -> vec@vec3:vec3(vec@vec3:vec3(float())).
look_at_lh(Eye, Center, Up) ->
look_to_lh(vec@vec3f:subtract(Center, Eye), Up).
-file("src/matrix/mat3f.gleam", 280).
?DOC(
" Creates a right-handed view matrix using a camera position, a focal point and an up\n"
" direction.\n"
"\n"
" For a view coordinate system with `+X=right`, `+Y=up` and `+Z=back`.\n"
).
-spec look_at_rh(
vec@vec3:vec3(float()),
vec@vec3:vec3(float()),
vec@vec3:vec3(float())
) -> vec@vec3:vec3(vec@vec3:vec3(float())).
look_at_rh(Eye, Center, Up) ->
look_to_rh(vec@vec3f:subtract(Center, Eye), Up).
-file("src/matrix/mat3f.gleam", 285).
?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", 290).
?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", 295).
?DOC(" Takes the absolute value of each element in the `Mat3f`.\n").
-spec absolute_value(vec@vec3:vec3(vec@vec3:vec3(float()))) -> vec@vec3:vec3(vec@vec3:vec3(float())).
absolute_value(Mat) ->
vec@vec3:map(Mat, fun vec@vec3f:absolute_value/1).
-file("src/matrix/mat3f.gleam", 300).
?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", 305).
?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", 310).
?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", 321).
?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", 194).
?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 = matrix@internal@projection:to_yz(_pipe),
_pipe@2 = vec@vec2:map(
_pipe@1,
fun matrix@internal@projection:to_yz/1
),
matrix@mat2f:determinant(_pipe@2)
end,
Xy = begin
_pipe@3 = Mat,
_pipe@4 = matrix@internal@projection:to_xz(_pipe@3),
_pipe@5 = vec@vec2:map(
_pipe@4,
fun matrix@internal@projection:to_yz/1
),
_pipe@6 = vec@vec2:swap(_pipe@5),
matrix@mat2f:determinant(_pipe@6)
end,
Xz = begin
_pipe@7 = Mat,
_pipe@8 = matrix@internal@projection:to_xy(_pipe@7),
_pipe@9 = vec@vec2:map(
_pipe@8,
fun matrix@internal@projection:to_yz/1
),
matrix@mat2f:determinant(_pipe@9)
end,
Yx = begin
_pipe@10 = Mat,
_pipe@11 = matrix@internal@projection:to_yz(_pipe@10),
_pipe@12 = vec@vec2:map(
_pipe@11,
fun matrix@internal@projection:to_xz/1
),
_pipe@13 = vec@vec2:swap(_pipe@12),
matrix@mat2f:determinant(_pipe@13)
end,
Yy = begin
_pipe@14 = Mat,
_pipe@15 = matrix@internal@projection:to_xz(_pipe@14),
_pipe@16 = vec@vec2:map(
_pipe@15,
fun matrix@internal@projection:to_xz/1
),
matrix@mat2f:determinant(_pipe@16)
end,
Yz = begin
_pipe@17 = Mat,
_pipe@18 = matrix@internal@projection:to_xy(_pipe@17),
_pipe@19 = vec@vec2:map(
_pipe@18,
fun matrix@internal@projection:to_xz/1
),
_pipe@20 = vec@vec2:swap(_pipe@19),
matrix@mat2f:determinant(_pipe@20)
end,
Zx = begin
_pipe@21 = Mat,
_pipe@22 = matrix@internal@projection:to_yz(_pipe@21),
_pipe@23 = vec@vec2:map(
_pipe@22,
fun matrix@internal@projection:to_xy/1
),
matrix@mat2f:determinant(_pipe@23)
end,
Zy = begin
_pipe@24 = Mat,
_pipe@25 = matrix@internal@projection:to_xz(_pipe@24),
_pipe@26 = vec@vec2:map(
_pipe@25,
fun matrix@internal@projection:to_xy/1
),
_pipe@27 = vec@vec2:swap(_pipe@26),
matrix@mat2f:determinant(_pipe@27)
end,
Zz = begin
_pipe@28 = Mat,
_pipe@29 = matrix@internal@projection:to_xy(_pipe@28),
_pipe@30 = vec@vec2:map(
_pipe@29,
fun matrix@internal@projection:to_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", 315).
?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).
-file("src/matrix/mat3f.gleam", 328).
?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", 335).
?DOC(
" Returns a matrix containing the reciprocal of each element of the `Mat3f`.\n"
"\n"
" If any of the elements is zero, an error is returned.\n"
).
-spec reciprocal(vec@vec3:vec3(vec@vec3:vec3(float()))) -> {ok,
vec@vec3:vec3(vec@vec3:vec3(float()))} |
{error, nil}.
reciprocal(Mat) ->
_pipe@2 = vec@vec3:map(Mat, fun(Column) -> _pipe = Column,
_pipe@1 = vec@vec3:map(
_pipe,
fun(_capture) -> gleam@float:divide(1.0, _capture) end
),
vec@vec3:result(_pipe@1) end),
vec@vec3:result(_pipe@2).
-file("src/matrix/mat3f.gleam", 345).
?DOC(" Sums a list of `Mat3f`s.\n").
-spec sum(list(vec@vec3:vec3(vec@vec3:vec3(float())))) -> vec@vec3:vec3(vec@vec3:vec3(float())).
sum(Mats) ->
gleam@list:fold(
Mats,
{vec3,
{vec3, +0.0, +0.0, +0.0},
{vec3, +0.0, +0.0, +0.0},
{vec3, +0.0, +0.0, +0.0}},
fun add/2
).
-file("src/matrix/mat3f.gleam", 350).
?DOC(" Multiplies a list of `Mat3f`s.\n").
-spec product(list(vec@vec3:vec3(vec@vec3:vec3(float())))) -> vec@vec3:vec3(vec@vec3:vec3(float())).
product(Mats) ->
gleam@list:fold(
Mats,
{vec3,
{vec3, 1.0, +0.0, +0.0},
{vec3, +0.0, 1.0, +0.0},
{vec3, +0.0, +0.0, 1.0}},
fun multiply/2
).