defmodule AgentSea.Vector do @moduledoc "Small vector math: dot product, L2 norm, normalization, cosine similarity." @type t :: [float()] @spec dot(t(), t()) :: float() def dot(a, b) do a |> Enum.zip(b) |> Enum.reduce(0.0, fn {x, y}, acc -> acc + x * y end) end @spec norm(t()) :: float() def norm(vec), do: :math.sqrt(Enum.reduce(vec, 0.0, fn x, acc -> acc + x * x end)) @doc "Scale a vector to unit length (returns it unchanged if it's the zero vector)." @spec normalize(t()) :: t() def normalize(vec) do n = norm(vec) if n == 0.0, do: vec, else: Enum.map(vec, &(&1 / n)) end @doc "Cosine similarity in [-1, 1] (0.0 if either vector is zero)." @spec cosine(t(), t()) :: float() def cosine(a, b) do na = norm(a) nb = norm(b) if na == 0.0 or nb == 0.0, do: 0.0, else: dot(a, b) / (na * nb) end end