#!/usr/bin/env sh # # Modified version of bash mandelbrot from Mecki stackoverflow.com/users/15809 # found at https://stackoverflow.com/a/63749612/1765658 # Avoiding forks and running bc as background task, reducing # execution time, from many hours to less than 10' (on my desktop) # # Modified version for POSIX shell by Léa Gris: # https://gist.github.com/leagris/59e1b7e72462024b278652696f375e71 # Improved to addressing fifos by FDs. BAILOUT=16 MAX_ITERATIONS=1000 ALPHWIDTH=$(( $(tput cols) / 2 )) AWIDE=$(( ALPHWIDTH -1 )) bcin=$(mktemp -u) bcout=$(mktemp -u) mkfifo "$bcin" "$bcout" exec 8<>"$bcin" exec 9<>"$bcout" bc -l <"$bcin" >"$bcout" & echo "scale=16;bailout=$BAILOUT;alphwidth=$ALPHWIDTH;0" >&8 read -r foo <&9 # Wait for bc before rm fifos rm "$bcin" "$bcout" bc() { retval=$1 shift printf %s\\n "$@" >&8 # shellcheck disable=SC2229 # No nameref support on older Bash read -r "$retval" <&9 } iterate () { # $1 is x # $2 is y zi=0 zr=0 i=0 cr= bc cr "$2 - 0.5" while true do temp=0 zr2=0 zi2=0 i=$((i + 1)) bc zr2 "($zr * $zr) - ($zi * $zi) + $cr" bc zi2 "(($zr * $zi) * 2) + $1" bc temp "(($zi * $zi) + ($zr * $zr)) > bailout" [ "$temp" -eq 1 ] && return "$i" [ "$i" -gt "$MAX_ITERATIONS" ] && return 0 zr=$zr2 zi=$zi2 done } mandelbrot () { y=$((0 - AWIDE)) while [ "$y" -lt "$AWIDE" ] do printf \\n x=$((0 - AWIDE)) while [ "$x" -lt "$AWIDE" ] do xi=0 yi=0 ires= bc xi "$x / alphwidth" bc yi "$y / alphwidth" iterate "$xi" "$yi" ires=$? if [ "$ires" -eq 0 ] then printf "*" else printf " " fi x=$((x + 1)) done y=$((y + 1)) done printf \\n } mandelbrot