Packages

Elixir Linear Algebra (ELA for short) contains functionality for working with both vectors and matrices.

Current section

Files

Jump to
ela lib vector.ex
Raw

lib/vector.ex

defmodule ELA.Vector do
alias :math, as: Math
@moduledoc"""
Contains operations for working with vectors.
"""
@doc"""
Returns an empty vector with provided dimension.
"""
@spec new(number) :: [number]
def new(n) when not is_number(n),
do: raise(ArgumentError, "Size provide has to be a number.")
def new(n) do
for _ <- 1..n, do: 0
end
@doc"""
Performs elementwise addition.
"""
@spec add([number], [number]) :: [number]
def add(u, v) when length(u) !== length(v),
do: raise(ArgumentError, "The number of elements in the vectors must match.")
def add(u, v) do
for {a, b} <- Enum.zip(u, v), do: a + b
end
@doc"""
Performs elementwise subtraction.
"""
@spec sub([number], [number]) :: [number]
def sub(u, v) when length(u) !== length(v),
do: raise(ArgumentError, "The number of elements in the vectors must match.")
@spec sub([number], [number]) :: [number]
def sub(u, v) do
add(u, Enum.map(v, fn(x) -> -x end))
end
@doc"""
Performs elementwise multiplication between two vectors.
This is the Hadmard product, but for vectors.
"""
@spec hadmard([number], [number]) :: [number]
def hadmard(u, v) when length(u) !== length(v),
do: raise(ArgumentError, "The number of elements in the vectors must match.")
def hadmard(u, v) do
Enum.zip(u, v) |> Enum.map(fn({a, b}) -> a*b end)
end
@doc"""
Calculates the cross product.
Is only defined for vectors with size three.
"""
@spec cross([number], [number]) :: [number]
def cross(u, v) when length(u) !== 3 and length(v) !== 3,
do: raise(ArgumentError, "The cross product is only defined for vectors with three elements.")
def cross(u, v) do
u = List.to_tuple(u)
v = List.to_tuple(v)
[elem(u, 1)*elem(v, 2) - elem(u, 2)*elem(v, 1),
elem(u, 2)*elem(v, 0) - elem(u, 0)*elem(v, 2),
elem(u, 0)*elem(v, 1) - elem(u, 1)*elem(v, 0)]
end
@doc"""
Elementwise multiplication with a scalar.
"""
@spec scalar([number], number) :: [number]
def scalar(v, s) do
Enum.map(v, fn(x) -> x*s end)
end
@doc"""
Calculates the dot product.
Multiplying empty vectors return 0.
"""
@spec dot([number], [number]) :: number
def dot(u, v) when length(u) !== length(v),
do: raise(ArgumentError, "The number of elements in the vectors must match.")
def dot(u, v) do
Enum.zip(u, v) |> Enum.reduce(0, fn({a, b}, acc) -> acc + a*b end)
end
@doc"""
Transponates the vector. Column vectors are two-dimensional.
"""
def transp(v) when is_number(hd(v)) do
Enum.map(v, fn(x) -> [x] end)
end
def transp(v) when is_list(hd(v)) do
List.flatten(v)
end
@doc"""
Calculates the euclidian norm of a vector.
"""
@spec norm([number]) :: number
def norm(v) do
Enum.reduce(v, 0, fn(e, acc) -> acc + Math.pow(e, 2) end)
|> Math.sqrt()
end
end