Skip to content

Instantly share code, notes, and snippets.

@epfahl
Created March 14, 2024 14:48
Show Gist options
  • Save epfahl/819fee40945ae23a292544f03170971b to your computer and use it in GitHub Desktop.
Save epfahl/819fee40945ae23a292544f03170971b to your computer and use it in GitHub Desktop.
defmodule PLF do
@doc """
Given a list of `{x, y}` nodes that the function must pass through, return
a function any input `x`.
For inputs less than the minimum `x` values among the nodes, extrapolate
with a constant equal to the `y` value of the min-`x` node. Similar
extrapolation occurs for `x` larger than the max-`x` node.
Note: When the number of nodes is large, this can be made more efficient
with a binary search or, perhaps, the alias method used to generate discrete
random variates.
"""
def build(nodes) do
nodes = Enum.sort_by(nodes, fn {x, _} -> x end)
{x_first, y_first} = List.first(nodes)
{x_last, y_last} = List.last(nodes)
fn x ->
cond do
x < x_first ->
y_first
x >= x_last ->
y_last
true ->
[{x1, y1}, {x2, y2}] =
nodes
|> Enum.chunk_every(2, 1, :discard)
|> Enum.find(fn [{x1, _}, {x2, _}] -> x1 <= x and x < x2 end)
y1 + (x - x1) * (y2 - y1) / (x2 - x1)
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment