Current section

Files

Jump to
exun lib exun_der.ex
Raw

lib/exun_der.ex

defmodule Exun.Der do
alias Exun.Math
alias Exun.Fun
@moduledoc """
Derivate expressions
"""
@zero {:numb, 0, 1}
@uno {:numb, 1, 1}
@doc """
Derive function for variable x, may be an ast or an expresion in text mode
```
deriv("sin(x)","x")
-> cos(x)*x'x
```
Or an AST, for internal use of library
```
deriv({:vari,"x"},"x")
-> {:numb,1}
```
"""
def deriv(txt, x) when is_binary(txt) and is_binary(x) do
ast = Exun.new(txt).ast
deriv(ast, x)
# |> IO.inspect(label: "reduced")
|> Exun.UI.tostr()
end
def deriv(ast, name) when is_tuple(ast) and is_binary(name) do
der(ast, {:vari, name})
end
defp der({:deriv, fun, x1}, x2) do
der(der(fun, x1), x2)
end
defp der({:fcall, name, args}, x) do
search_name = name <> "(F)"
cond do
(bfunc = Fun.base()[search_name]) != nil ->
ast = Exun.new(elem(bfunc, 1)).ast
mapdef = %{{:vari, "F"} => args |> List.first(), {:vari, "x"} => {:vari, "x"}}
Exun.replace(ast, mapdef)
(cfunc = Fun.compounds()[search_name]) != nil ->
ast = Exun.new(cfunc).ast
mapdef = %{{:vari, "F"} => args |> List.first(), {:vari, "x"} => {:vari, "x"}}
Exun.replace(ast, mapdef)
|> der(x)
true ->
{:deriv, {:fcall, name, args}, x}
end
# |> IO.inspect(label: "der fcall")
end
defp der({:minus, a}, x), do: {:minus, der(a, x)}
defp der({:numb, _, _}, _x), do: @zero
defp der({:unit, _uv, _ut}, _x), do: @zero
defp der({:vari, var}, {:vari, x}), do: if(var == x, do: @uno, else: @zero)
defp der({:elev, base, expon}, x),
do:
Math.mult(
{:elev, base, expon},
Math.suma(
Math.mult(der(expon, x), {:fcall, "ln", [base]}),
Math.mult(expon, Math.divi(der(base, x), base))
)
)
defp der({:integ, f, x}, x), do: f
defp der({{:m, :suma}, lst}, x),
do: {{:m, :suma}, Enum.map(lst, &der(&1, x))}
defp der({{:m, :mult}, [a]}, x), do: der(a, x)
defp der({{:m, :mult}, lst}, x) when is_list(lst) do
prim = List.first(lst)
segu = {{:m, :mult}, List.delete(lst, prim)}
Math.suma(
Math.mult(prim, der(segu, x)),
Math.mult(der(prim, x), segu)
)
end
defp der(f, x) do
{:deriv, f, x}
end
end