Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Dual Number on Elixir
import Kernel, except: [+: 1, +: 2, -: 1, -: 2, *: 2, /: 2]
defprotocol Arithmetic do
def left + right
def left - right
def left * right
def left / right
def +value
def -value
end
defimpl Arithmetic, for: Integer do
def left + right, do: Kernel.+(left , right)
def left - right, do: Kernel.-(left , right)
def left * right, do: Kernel.*(left , right)
def left / right, do: Kernel./(left , right)
def +value, do: Kernel.+(value)
def -value, do: Kernel.-(value)
end
defimpl Arithmetic, for: Integer do
def left + right, do: Kernel.+(left , right)
def left - right, do: Kernel.-(left , right)
def left * right, do: Kernel.*(left , right)
def left / right, do: Kernel./(left , right)
def +value, do: Kernel.+(value)
def -value, do: Kernel.-(value)
end
defmodule DualNumber do
import Arithmetic
defstruct a: 0, b: 0
def conj(d) do
%DualNumber{ a: d.a, b: -d.b}
end
defimpl Inspect do
def inspect(%DualNumber{a: a, b: b}, _opts) do
"#{a}+#{b}ε"
end
end
end
defimpl Arithmetic, for: DualNumber do
def left + right do
%DualNumber{ a: Kernel.+(left.a, right.a),
b: Kernel.+(left.b, right.b) }
end
def left - right do
%DualNumber{ a: Kernel.-(left.a, right.a),
b: Kernel.-(left.b, right.b) }
end
def left * right do
%DualNumber{ a: Kernel.*(left.a, right.a),
b: Kernel.+(Kernel.*(left.a, right.b), Kernel.*(left.b, right.a)) }
end
def left / right do
(left * %DualNumber{a: right.a, b: Kernel.-(right.b)}) / %DualNumber{a: Kernel.*(right.a, right.a), b: 0}
end
def +value, do: value
def -value, do: %DualNumber{a: Kernel.-(value.a), b: Kernel.-(value.b)}
end
defmodule Test do
import Arithmetic
import DualNumber
def f(x) do
(%DualNumber{a: 4, b: 0} * x + %DualNumber{a: 3, b: 0}) * x + %DualNumber{a: 2, b: 0}
end
def df(x) do
%DualNumber{a: 8, b: 0} * x + %DualNumber{a: 3, b: 0}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.