Current section

Files

Jump to
exun lib exun_collect.ex
Raw

lib/exun_collect.ex

defmodule Exun.Collect do
@moduledoc """
Collect Math expression, try to simplify
"""
alias Exun.Simpl
alias Exun.Math
alias Exun.Eq
@doc """
Main collecting function. Try to simplify tree withou chaging its value
Gets and returns an AST, as produced by Exun.parse.
"""
def coll(tree) do
newtree =
tree
# |> IO.inspect(label: "make00, orig->mkrec")
|> Simpl.mkrec()
|> expand_rec()
|> Simpl.mkrec()
if Eq.eq(newtree, tree), do: newtree, else: coll(newtree)
end
@doc """
Expand mult(sum) to try collect more
"""
def expand_rec(ast) do
newast = expand(ast)
if ast == newast do
newast
else
expand_rec(newast)
end
end
defp expand(ast) do
case ast do
{:numb, _, _} ->
ast
{:vari, _} ->
ast
{:deriv, f, v} ->
{:deriv, expand(f), v}
{:integ, f, v} ->
{:integ, expand(f), v}
{:fcall, f, args} ->
{:fcall, f, Enum.map(args, &expand(&1))}
{:unit, n, t} ->
{:unit, expand(n), t}
{:minus, a} ->
{:minus, expand(a)}
{:elev, a, {:numb, n, d}} when n > 0 and d == 1 and floor(n) == n ->
{{:m, :mult}, List.duplicate(a, floor(n))}
{:elev, b, e} ->
{:elev, expand(b), expand(e)}
{{:vector, s}, l} ->
{{:vector, s}, l |> Enum.map(&expand/1)}
{{t, rs, cs}, list, mr, mc} ->
{{t, rs, cs}, list |> Enum.map(&expand/1), mr, mc}
{{:m, :suma}, l} ->
{{:m, :suma}, Enum.map(l, &expand(&1))}
{{:m, :mult}, l} ->
tsuma = List.keyfind(l, {:m, :suma}, 0)
if tsuma != nil do
{_, lsuma} = tsuma
# Convert {:m,:mult} to {:m,:suma}
remain = {{:m, :mult}, List.delete(l, tsuma)}
{{:m, :suma}, Enum.map(lsuma, &Math.mult(remain, &1))}
else
{{:m, :mult}, Enum.map(l, &expand(&1))}
end
unknown ->
throw("Unknown at collect: #{Exun.UI.tostr(unknown)}")
end
end
end