Skip to content

Instantly share code, notes, and snippets.

@corpsmoderne
Created October 20, 2021 15:43
Show Gist options
  • Save corpsmoderne/7ff1cd15d84b61f2efc2edee783c5e20 to your computer and use it in GitHub Desktop.
Save corpsmoderne/7ff1cd15d84b61f2efc2edee783c5e20 to your computer and use it in GitHub Desktop.
Mandelbrot in Elixir
defmodule Mandel do
defp mandel(x0, y0, zoom, iter_max) do
loop = fn
(_, _, _, ^iter_max) -> 0
(self, x, y, iter) ->
x_x = x * x |> div(zoom)
y_y = y * y |> div(zoom)
if x_x + y_y > 4 * zoom do
iter
else
self.(self, x_x - y_y + x0,
(2 * x * y |> div(zoom)) + y0,
iter+1)
end
end
loop.(loop, x0, y0, 0)
end
defp to_color(v) do
<< rem(v*v, 256), 0, rem(v*v*v, 256)>>
end
defp render_line(y, fromx, tox, zoom) do
for x <- fromx..tox-1 do
mandel(x, y, zoom, 128)
|> to_color
end
|> Enum.join()
end
defp render_par_({w, h}, {offx, offy}, z) do
n = System.schedulers_online
to = self()
for i <- 0..n-1 do
spawn(fn ->
msg = for y <- 0..(h-1) // n do
{y+i, render_line(y+offy+i, offx, w+offx, z)}
end
send to, msg
end)
end
for _ <- 0..n-1 do
receive do
msg -> msg
end
end
|> List.flatten()
|> Enum.sort(fn {i,_}, {j,_} -> i<j end)
|> Enum.map(fn {_,l} -> l end)
|> Enum.join()
end
defp write_image(buff, filename, w, h) do
File.write(filename, "P6\n#{w} #{h}\n255\n" <> buff, [:binary])
end
def render_par(filename \\ "out.ppm",
{w, h} \\ {1600, 1200},
{ox, oy} \\ { -2400, -800 },
zoom \\ 3000) do
offx = ox-div(w,2)
offy = oy-div(h,2)
render_par_({w, h}, {offx, offy}, zoom)
|> write_image(filename, w, h)
end
def render(filename \\ "out.ppm",
{w, h} \\ {1600, 1200},
{ox, oy} \\ { -2400, -800 },
zoom \\ 3000) do
offx = ox-div(w,2)
offy = oy-div(h,2)
for y <- 0..(h-1) , x <- 0..(w-1) do
mandel(x+offx, y+offy, zoom, 128)
|> to_color
end
|> Enum.join()
|> write_image(filename, w, h)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment