Packages

This is an effort to try and replicate some of the NumPy modules in elixir-lang.

Current section

Files

Jump to
num_ex lib Polynomial.ex
Raw

lib/Polynomial.ex

defmodule Polynomial do
@moduledoc"""
A module to perform various operations on Polynomials.
"""
defp main(a, b) do
lena = Enum.count(a)
lenb = Enum.count(b)
condition(a, b,lena, lenb)
end
defp take(c, len1, len2), do: Enum.take(c, len1-len2)
defp condition(a, b, lena, lenb) do
cond do
lena > lenb -> take(a, lena, lenb)
lenb > lena -> take(b, lenb, lena)
true -> []
end
end
@doc"""
Returns the sum of two Polynomials
## Examples
iex> Polynomial.polyadd([2, 3, 7], [1, 5])
[2, 4, 12]
"""
@spec polyadd(list, list) :: list
def polyadd(a, b) do
list2 = main(a, b)
list1 = List.zip([Enum.reverse(a), Enum.reverse(b)])
add(list1, list2)
end
defp add(d, c) do
Enum.map(d, fn({x, y}) -> x + y end) ++ Enum.reverse(c)
|> Enum.reverse
end
@doc"""
Returns the difference of two Polynomials
## Examples
iex> Polynomial.polysub([2, 3, 7], [1, 5, 9])
[1, -2, -2]
"""
@spec polysub(list, list) :: list
def polysub(a, b) do
list2 = main(a, b)
list1 = List.zip([Enum.reverse(a), Enum.reverse(b)])
sub(list1, list2)
end
defp sub(d, c) do
Enum.map(d,fn({x, y}) -> x - y end) ++ Enum.reverse(c)
|> Enum.reverse
end
@doc"""
Returns the product of two Polynomials
## Examples
iex> Polynomial.polymul([5, 1, 3], [-1, 2])
[-5, 9, -1, 6]
"""
@spec polymul(list, list) :: list
def polymul(a, b) do
degree1 = Enum.count(a) - 1
degree2 = Enum.count(b) - 1
n = degree1 + degree2 + 1
result = List.duplicate(0, n)
resultpoly = for i <- 0..degree1, j <- 0..degree2, do: List.update_at(result, i+j ,&(&1 + (Enum.at(a, i) * Enum.at(b, j))))
resultpoly
|> Enum.zip
|> Enum.map(fn(x) -> Tuple.to_list(x) end)
|> Enum.map(fn(x) -> Enum.sum(x) end)
end
@doc"""
Returns the Polynomial multiplied with a given coefficient
## Examples
iex> Polynomial.polymulx([4, 5, -2], 2)
[8, 10, -4]
"""
@spec polymulx(list, integer) :: list
def polymulx(poly, x), do: Enum.map(poly, fn(m) -> m * x end)
@doc"""
Returns the quotient and remainder of two Polynomials
## Examples
iex> Polynomial.polydiv([4, 5, 2], [2, 1])
{[2, 1], [1]}
"""
@spec polydiv(list, list) :: {list, list}
def polydiv(_, []), do: raise ArgumentError, "denominator is zero"
def polydiv(_, [0]), do: raise ArgumentError, "denominator is zero"
def polydiv(f, g) when length(f) < length(g), do: {[0], f}
def polydiv(f, g) do
{q, r} = polydiv(g, [], f)
if q == [], do: [0]
if r == [], do: [0]
{q, r}
end
defp polydiv(g, q, r) when length(r) < length(g), do: {q, r}
defp polydiv(g, q, r) do
p = div(hd(r), hd(g))
temprem = Enum.zip(r, g)
|> Enum.with_index
|> Enum.reduce(r, fn {{n, d}, i}, acc ->
List.replace_at(acc, i, n - p * d)
end)
polydiv(g, q++[p], tl(temprem))
end
@doc"""
Returns the derivative of the given Polynomial
## Examples
iex> Polynomial.polyder([6, -1, 3, 2])
[18, -2, 3]
"""
@spec polyder(list) :: list
def polyder(a) do
degree = Enum.count(a) - 1
a |> Enum.with_index
|> Enum.map(fn({x, y}) -> x * (degree - y) end)
|> Enum.take(degree)
end
@doc"""
Returns the the coefficients of the polynomial raised to the given power
## Examples
iex> Polynomial.polypow([6, -1, 3], 2)
[36, 1, 9]
"""
@spec polyadd(list, integer) :: list
def polypow(polynomial, power) do
Enum.map(polynomial, fn(x) -> round(:math.pow(x, power)) end)
end
#def quadraticroots(a, b, c) do
# d = b * b - 4 * a * c
# a2 = a * 2
# {r1, r2} =
# cond do
# d > 0 ->
# sd = :math.sqrt(d)
# {(- b + sd) / a2, (- b - sd) / a2}
# d == 0 ->
# {- b / a2, - b / a2}
# true ->
# sd = :math.sqrt(-d)
# {(- b / a2) + (sd / a2), (- b / a2) - (sd / a2)}
# end
#end
end