Packages

Core mathematical functions for VIVA - sentient digital life. PAD emotions, Cusp catastrophe, Free Energy Principle, attractor dynamics.

Current section

Files

Jump to
viva_math src viva_math@vec2.erl
Raw

src/viva_math@vec2.erl

-module(viva_math@vec2).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/viva_math/vec2.gleam").
-export([zero/0, splat/1, from_polar/2, add/2, sub/2, scale/2, negate/1, dot/2, cross/2, length_squared/1, length/1, distance/2, normalize/1, lerp/3, clamp/3, rotate/2, perpendicular/1, angle/1, is_close/3]).
-export_type([vec2/0]).
-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(
" 2-D vector operations.\n"
"\n"
" Companion to `viva_math/vector` (which is dedicated to PAD/Vec3).\n"
" Useful for 2-D dynamics, planar geometry, polar coordinates, etc.\n"
).
-type vec2() :: {vec2, float(), float()}.
-file("src/viva_math/vec2.gleam", 13).
-spec zero() -> vec2().
zero() ->
{vec2, +0.0, +0.0}.
-file("src/viva_math/vec2.gleam", 17).
-spec splat(float()) -> vec2().
splat(Value) ->
{vec2, Value, Value}.
-file("src/viva_math/vec2.gleam", 21).
-spec from_polar(float(), float()) -> vec2().
from_polar(R, Theta) ->
{vec2, R * math:cos(Theta), R * math:sin(Theta)}.
-file("src/viva_math/vec2.gleam", 25).
-spec add(vec2(), vec2()) -> vec2().
add(A, B) ->
{vec2,
erlang:element(2, A) + erlang:element(2, B),
erlang:element(3, A) + erlang:element(3, B)}.
-file("src/viva_math/vec2.gleam", 29).
-spec sub(vec2(), vec2()) -> vec2().
sub(A, B) ->
{vec2,
erlang:element(2, A) - erlang:element(2, B),
erlang:element(3, A) - erlang:element(3, B)}.
-file("src/viva_math/vec2.gleam", 33).
-spec scale(vec2(), float()) -> vec2().
scale(V, S) ->
{vec2, erlang:element(2, V) * S, erlang:element(3, V) * S}.
-file("src/viva_math/vec2.gleam", 37).
-spec negate(vec2()) -> vec2().
negate(V) ->
{vec2, +0.0 - erlang:element(2, V), +0.0 - erlang:element(3, V)}.
-file("src/viva_math/vec2.gleam", 41).
-spec dot(vec2(), vec2()) -> float().
dot(A, B) ->
(erlang:element(2, A) * erlang:element(2, B)) + (erlang:element(3, A) * erlang:element(
3,
B
)).
-file("src/viva_math/vec2.gleam", 46).
?DOC(" 2-D \"cross\" returns the z-component of the 3-D cross product.\n").
-spec cross(vec2(), vec2()) -> float().
cross(A, B) ->
(erlang:element(2, A) * erlang:element(3, B)) - (erlang:element(3, A) * erlang:element(
2,
B
)).
-file("src/viva_math/vec2.gleam", 50).
-spec length_squared(vec2()) -> float().
length_squared(V) ->
dot(V, V).
-file("src/viva_math/vec2.gleam", 55).
?DOC(" Length √(x² + y²) — uses `hypot` to avoid overflow/underflow at extreme scales.\n").
-spec length(vec2()) -> float().
length(V) ->
viva_math@scalar:hypot(erlang:element(2, V), erlang:element(3, V)).
-file("src/viva_math/vec2.gleam", 59).
-spec distance(vec2(), vec2()) -> float().
distance(A, B) ->
length(sub(A, B)).
-file("src/viva_math/vec2.gleam", 63).
-spec normalize(vec2()) -> vec2().
normalize(V) ->
L = length(V),
case L =:= +0.0 of
true ->
zero();
false ->
{vec2, case L of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator -> erlang:element(2, V) / Gleam@denominator
end, case L of
+0.0 -> +0.0;
-0.0 -> -0.0;
Gleam@denominator@1 -> erlang:element(3, V) / Gleam@denominator@1
end}
end.
-file("src/viva_math/vec2.gleam", 71).
-spec lerp(vec2(), vec2(), float()) -> vec2().
lerp(A, B, T) ->
{vec2,
viva_math@scalar:lerp(erlang:element(2, A), erlang:element(2, B), T),
viva_math@scalar:lerp(erlang:element(3, A), erlang:element(3, B), T)}.
-file("src/viva_math/vec2.gleam", 75).
-spec clamp(vec2(), float(), float()) -> vec2().
clamp(V, Lo, Hi) ->
{vec2,
viva_math@scalar:clamp(erlang:element(2, V), Lo, Hi),
viva_math@scalar:clamp(erlang:element(3, V), Lo, Hi)}.
-file("src/viva_math/vec2.gleam", 80).
?DOC(" Rotate `v` by `theta` radians around the origin.\n").
-spec rotate(vec2(), float()) -> vec2().
rotate(V, Theta) ->
C = math:cos(Theta),
S = math:sin(Theta),
{vec2,
(erlang:element(2, V) * C) - (erlang:element(3, V) * S),
(erlang:element(2, V) * S) + (erlang:element(3, V) * C)}.
-file("src/viva_math/vec2.gleam", 87).
?DOC(" Perpendicular vector (90° counter-clockwise rotation).\n").
-spec perpendicular(vec2()) -> vec2().
perpendicular(V) ->
{vec2, +0.0 - erlang:element(3, V), erlang:element(2, V)}.
-file("src/viva_math/vec2.gleam", 92).
?DOC(" Angle in radians of `v` relative to the positive x-axis. Range (-π, π].\n").
-spec angle(vec2()) -> float().
angle(V) ->
math:atan2(erlang:element(3, V), erlang:element(2, V)).
-file("src/viva_math/vec2.gleam", 97).
?DOC(" Component-wise approximate equality.\n").
-spec is_close(vec2(), vec2(), float()) -> boolean().
is_close(A, B, Tol) ->
(gleam@float:absolute_value(erlang:element(2, A) - erlang:element(2, B)) =< Tol)
andalso (gleam@float:absolute_value(
erlang:element(3, A) - erlang:element(3, B)
)
=< Tol).