Created
April 14, 2026 07:43
-
-
Save tfc/2d30b290506f61277d1d9a3137bb69d6 to your computer and use it in GitHub Desktop.
Mandelbrot fractal in nix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| let | |
| pkgs = import <nixpkgs> {}; | |
| inherit (pkgs) lib; | |
| # minimal complex number library | |
| complex = { | |
| zero = { r = 0.0; i = 0.0; }; | |
| fromXY = r: i: { inherit r i; }; | |
| multiply = a: b: { | |
| r = a.r * b.r - a.i * b.i; | |
| i = a.r * b.i + a.i * b.r; | |
| }; | |
| add = a: b: { | |
| r = a.r + b.r; | |
| i = a.i + b.i; | |
| }; | |
| abs2 = { r, i }: r * r + i * i; | |
| }; | |
| toS = builtins.toString; | |
| # from floating point to integer, we're dropping after the decimal point | |
| toI = fl: lib.strings.toInt (builtins.head (builtins.split "\\." (builtins.toString fl))); | |
| # typical mandelbrot fractal iteration function | |
| iterate = cfg@{ threshold, limit }: point: n: current: | |
| let | |
| next = complex.add (complex.multiply current current) point; | |
| in | |
| if n >= threshold || complex.abs2 next > limit * limit | |
| then n | |
| else iterate cfg point (n + 1) next; | |
| # the bounds within the complex coordinate plane that we want to paint | |
| bounds = { | |
| x0 = -3; | |
| y0 = -1; | |
| x1 = 1; | |
| y1 = 1; | |
| }; | |
| step = 0.05; | |
| ranges = { | |
| x = lib.lists.range (toI (bounds.x0 / step)) (toI (bounds.x1 / step)); | |
| y = lib.lists.range (toI (bounds.y0 / step)) (toI (bounds.y1 / step)); | |
| }; | |
| map2d = f: map (y: map (x: f (step * x) (step * y)) ranges.x) ranges.y; | |
| cfg = { threshold = 5000; limit = 1000; }; | |
| result = | |
| let | |
| f = x: y: | |
| let | |
| c = complex.fromXY x y; | |
| in | |
| iterate cfg c 0 complex.zero; | |
| in | |
| map2d f; | |
| renderField = renderItem: field: | |
| let | |
| renderedField = map (map renderItem) field; | |
| in | |
| builtins.throw ("\n" + lib.strings.concatLines (map lib.concatStrings renderedField)); | |
| # cheap ASCII rasterization | |
| renderMandelbrotScore = n: | |
| let x = cfg.threshold / n; in | |
| if 1000 < x then "." | |
| else if 500 < x then "," | |
| else if 200 < x then ":" | |
| else if 100 < x then ";" | |
| else if 50 < x then "!" | |
| else if 20 < x then "/" | |
| else if 10 < x then "%" | |
| else if 5 < x then "?" | |
| else "#"; | |
| in | |
| renderField renderMandelbrotScore result | |
| # for debugging the values when rasterization looks off | |
| #renderField toS result |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| error: | |
| … while calling the 'throw' builtin | |
| at /Users/tfc/mb/default.nix:64:5: | |
| 63| in | |
| 64| builtins.throw ("\n" + lib.strings.concatLines (map lib.concatStrings renderedField)); | |
| | ^ | |
| 65| | |
| error: | |
| ...............................,,,,,,,,,,,,,,,,,,,,,,,,,::::#,,,,,,,,,,,,,,...... | |
| .............................,,,,,,,,,,,,,,,,,,,,,,,,,,,::;:,,,,,,,,,,,,,,,,..... | |
| ............................,,,,,,,,,,,,,,,,,,,,,,,,,,,::;;::,,,,,,,,,,,,,,,..... | |
| ...........................,,,,,,,,,,,,,,,,,,,,,,,,,,,:;:;#::,,,,,,,,,,,,,,,,.... | |
| .........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,::####::,,,,,,,,,,,,,,,,... | |
| ........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,:::####;:,,,,,,,,,,,,,,,,... | |
| .......................,,,,,,,,,,,,,,,,,,,,,,,,,::::::::####::::,,,:,,,,,,,,,,,.. | |
| ......................,,,,,,,,,,,,,,,,,,,,,,,,,,:!::!://!!!/;;:;::::,,,,,,,,,,,.. | |
| .....................,,,,,,,,,,,,,,,,,,,,,,,,,,::;#:;##########::::::,,,,,,,,,,.. | |
| ....................,,,,,,,,,,,,,,,,,,,,,,,,,,,::%##############?##;:,,,,,,,,,,,. | |
| ....................,,,,,,,,,,,,,,,,,,,,,,,,,,:::!#################:,,,,,,,,,,,,. | |
| ...................,,,,,,,,,,,,,,,,,,,,,,,,,,::/;#################;::,,,,,,,,,,,. | |
| ..................,,,,,,,,,,,,,,,,,:,,,,,,,,::::###################:::,,,,,,,,,,. | |
| .................,,,,,,,,,,,,,,,,,::::::::::::/#####################?:,,,,,,,,,,, | |
| .................,,,,,,,,,,,,,,,,,,:::::;:::::;#####################::,,,,,,,,,,, | |
| ................,,,,,,,,,,,,,,,,,,:::#;%#/;:::######################::,,,,,,,,,,, | |
| ................,,,,,,,,,,,,,,,,,,:::#######::######################;:,,,,,,,,,,, | |
| ................,,,,,,,,,,,,,,,,::::#########:######################;,,,,,,,,,,,, | |
| ................,,,,,,,,,,,,,,,:::::#########;######################:,,,,,,,,,,,, | |
| ...............,,,,,,,,,,:,,:::::/#;#########!#####################:,,,,,,,,,,,,, | |
| ...............,,,,,##############################################::,,,,,,,,,,,,, | |
| ...............,,,,,,,,,,:,,:::::/#;#########!#####################:,,,,,,,,,,,,, | |
| ................,,,,,,,,,,,,,,,:::::#########;######################:,,,,,,,,,,,, | |
| ................,,,,,,,,,,,,,,,,::::#########:######################;,,,,,,,,,,,, | |
| ................,,,,,,,,,,,,,,,,,,:::#######::######################;:,,,,,,,,,,, | |
| ................,,,,,,,,,,,,,,,,,,:::#;%#/;:::######################::,,,,,,,,,,, | |
| .................,,,,,,,,,,,,,,,,,,:::::;:::::;#####################::,,,,,,,,,,, | |
| .................,,,,,,,,,,,,,,,,,::::::::::::/#####################?:,,,,,,,,,,, | |
| ..................,,,,,,,,,,,,,,,,,:,,,,,,,,::::###################:::,,,,,,,,,,. | |
| ...................,,,,,,,,,,,,,,,,,,,,,,,,,,::/;#################;::,,,,,,,,,,,. | |
| ....................,,,,,,,,,,,,,,,,,,,,,,,,,,:::!#################:,,,,,,,,,,,,. | |
| ....................,,,,,,,,,,,,,,,,,,,,,,,,,,,::%##############?##;:,,,,,,,,,,,. | |
| .....................,,,,,,,,,,,,,,,,,,,,,,,,,,::;#:;##########::::::,,,,,,,,,,.. | |
| ......................,,,,,,,,,,,,,,,,,,,,,,,,,,:!::!://!!!/;;:;::::,,,,,,,,,,,.. | |
| .......................,,,,,,,,,,,,,,,,,,,,,,,,,::::::::####::::,,,:,,,,,,,,,,,.. | |
| ........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,:::####;:,,,,,,,,,,,,,,,,... | |
| .........................,,,,,,,,,,,,,,,,,,,,,,,,,,,,,::####::,,,,,,,,,,,,,,,,... | |
| ...........................,,,,,,,,,,,,,,,,,,,,,,,,,,,:;:;#::,,,,,,,,,,,,,,,,.... | |
| ............................,,,,,,,,,,,,,,,,,,,,,,,,,,,::;;::,,,,,,,,,,,,,,,..... | |
| .............................,,,,,,,,,,,,,,,,,,,,,,,,,,,::;:,,,,,,,,,,,,,,,,..... | |
| ...............................,,,,,,,,,,,,,,,,,,,,,,,,,::::#,,,,,,,,,,,,,,...... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment