Mandelbrot in ASCII in Mojo
The demo Mojo is known for - escape-time rendering, four columns at a time.
comptime F4 = SIMD[DType.float64, 4]
comptime I4 = SIMD[DType.int32, 4]
comptime WIDTH = 60
comptime HEIGHT = 24
comptime MAX_ITERS = 40
def escape_counts(cx: F4, cy: F4) -> I4:
var zx = F4(0.0)
var zy = F4(0.0)
var counts = I4(0)
for _ in range(MAX_ITERS):
var alive = (zx * zx + zy * zy).le(F4(4.0))
if not alive.reduce_or():
break
counts += alive.select(I4(1), I4(0))
var next_x = zx * zx - zy * zy + cx
zy = 2.0 * zx * zy + cy
zx = next_x
return counts
def main():
var shades: List[String] = [" ", ".", ":", "-", "=", "+", "*", "#", "@"]
var levels = len(shades) - 1
for row in range(HEIGHT):
var cy = F4(-1.2 + 2.4 * Float64(row) / Float64(HEIGHT))
var line = String()
for block in range(0, WIDTH, 4):
var cx = F4(0.0)
for lane in range(4):
var column = Float64(block + lane)
cx[lane] = -2.2 + 3.0 * column / Float64(WIDTH)
var counts = escape_counts(cx, cy)
for lane in range(4):
line += shades[Int(counts[lane]) * levels // MAX_ITERS]
print(line)
How it works
escape_countsiteratesz = z * z + con four points in parallel.- A mask counts only the lanes still alive, and breaks once all have escaped.
- Each count picks a shade character, drawing a 60 by 24 grid.
Keywords and builtins used here
DTypeFloat64IntListSIMDStringbreakdefescape_countsforiflenmainprintrangereturnvar
The run, in numbers
- Lines
- 37
- Characters to type
- 957
- Tokens
- 318
- Three-star pace
- 65 tpm
At the three-star pace of 65 tokens a minute, this run takes about 294 seconds.
Step 1 of 2 in Encore, step 21 of 22 in Parameters & SIMD.