mirror of
https://github.com/johnkerl/miller.git
synced 2026-01-24 02:36:15 +00:00
100 lines
2.6 KiB
Text
100 lines
2.6 KiB
Text
# Mandelbrot set generator: simple example of Miller DSL as programming language.
|
|
begin {
|
|
# Set defaults
|
|
@rcorn = -2.0;
|
|
@icorn = -2.0;
|
|
@side = 4.0;
|
|
@iheight = 50;
|
|
@iwidth = 100;
|
|
@maxits = 100;
|
|
@levelstep = 5;
|
|
@chars = "@X*o-."; # Palette of characters to print to the screen.
|
|
@verbose = false;
|
|
@do_julia = false;
|
|
@jr = 0.0; # Real part of Julia point, if any
|
|
@ji = 0.0; # Imaginary part of Julia point, if any
|
|
}
|
|
|
|
# Here, we can override defaults from an input file (if any). In Miller's
|
|
# put/filter DSL, absent-null right-hand sides result in no assignment so we
|
|
# can simply put @rcorn = $rcorn: if there is a field in the input like
|
|
# 'rcorn = -1.847' we'll read and use it, else we'll keep the default.
|
|
@rcorn = $rcorn;
|
|
@icorn = $icorn;
|
|
@side = $side;
|
|
@iheight = $iheight;
|
|
@iwidth = $iwidth;
|
|
@maxits = $maxits;
|
|
@levelstep = $levelstep;
|
|
@chars = $chars;
|
|
@verbose = $verbose;
|
|
@do_julia = $do_julia;
|
|
@jr = $jr;
|
|
@ji = $ji;
|
|
|
|
end {
|
|
if (@verbose) {
|
|
print "RCORN = ".@rcorn;
|
|
print "ICORN = ".@icorn;
|
|
print "SIDE = ".@side;
|
|
print "IHEIGHT = ".@iheight;
|
|
print "IWIDTH = ".@iwidth;
|
|
print "MAXITS = ".@maxits;
|
|
print "LEVELSTEP = ".@levelstep;
|
|
print "CHARS = ".@chars;
|
|
}
|
|
|
|
# Iterate over a matrix of rows and columns, printing one character for each cell.
|
|
for (int ii = @iheight-1; ii >= 0; ii -= 1) {
|
|
num pi = @icorn + (ii/@iheight) * @side;
|
|
for (int ir = 0; ir < @iwidth; ir += 1) {
|
|
num pr = @rcorn + (ir/@iwidth) * @side;
|
|
printn get_point_plot(pr, pi, @maxits, @do_julia, @jr, @ji);
|
|
}
|
|
print;
|
|
}
|
|
}
|
|
|
|
# This is a function to approximate membership in the Mandelbrot set (or Julia
|
|
# set for a given Julia point if do_julia == true) for a given point in the
|
|
# complex plane.
|
|
func get_point_plot(pr, pi, maxits, do_julia, jr, ji) {
|
|
num zr = 0.0;
|
|
num zi = 0.0;
|
|
num cr = 0.0;
|
|
num ci = 0.0;
|
|
|
|
if (!do_julia) {
|
|
zr = 0.0;
|
|
zi = 0.0;
|
|
cr = pr;
|
|
ci = pi;
|
|
} else {
|
|
zr = pr;
|
|
zi = pi;
|
|
cr = jr;
|
|
ci = ji;
|
|
}
|
|
|
|
int iti = 0;
|
|
bool escaped = false;
|
|
num zt = 0;
|
|
for (iti = 0; iti < maxits; iti += 1) {
|
|
num mag = zr*zr + zi+zi;
|
|
if (mag > 4.0) {
|
|
escaped = true;
|
|
break;
|
|
}
|
|
# z := z^2 + c
|
|
zt = zr*zr - zi*zi + cr;
|
|
zi = 2*zr*zi + ci;
|
|
zr = zt;
|
|
}
|
|
if (!escaped) {
|
|
return ".";
|
|
} else {
|
|
# The // operator is Miller's (pythonic) integer-division operator
|
|
int level = (iti // @levelstep) % strlen(@chars);
|
|
return substr(@chars, level, level);
|
|
}
|
|
}
|