{"id":16349,"date":"2020-07-07T22:37:52","date_gmt":"2020-07-08T02:37:52","guid":{"rendered":"https:\/\/scruss.com\/blog\/?p=16349"},"modified":"2022-07-24T10:38:59","modified_gmt":"2022-07-24T14:38:59","slug":"the-mandelbrot-set-before-mandelbrot","status":"publish","type":"post","link":"https:\/\/scruss.com\/blog\/2020\/07\/07\/the-mandelbrot-set-before-mandelbrot\/","title":{"rendered":"The Mandelbrot Set, before Mandelbrot"},"content":{"rendered":"\n<p>How many CPU hours did I burn in the early 1990s rendering bits of the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Mandelbrot_set\">Mandelbrot Set<\/a>? A <em>lot<\/em>, mainly because I was doing it in BASIC on an unexpanded 8 MHz Commodore Amiga A500. The image below that <a href=\"https:\/\/fraqtive.mimec.org\/\">Fraqtive<\/a> rendered in almost no time would have taken me days:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"652\" src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/mandelbrot-1024x652.jpg\" alt=\"\" class=\"wp-image-16352\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/mandelbrot-1024x652.jpg 1024w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/mandelbrot-320x204.jpg 320w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/mandelbrot-160x102.jpg 160w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/mandelbrot-768x489.jpg 768w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/mandelbrot-1200x764.jpg 1200w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/mandelbrot.jpg 1436w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>the squashed bug that started it all: the Mandelbrot set<\/figcaption><\/figure>\n\n\n\n<p>But it turns out that the first rendering of what we now call the Mandelbrot set wasn&#8217;t produced by Benoit Mandelbrot, but by Brooks &amp; Matelski a year or two earlier:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"793\" src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/brooksmatelski-fig2-1024x793.jpg\" alt=\"text plot of the Mandelbrot set with points inside set marked with asterisks\" class=\"wp-image-16350\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/brooksmatelski-fig2-1024x793.jpg 1024w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/brooksmatelski-fig2-320x248.jpg 320w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/brooksmatelski-fig2-160x124.jpg 160w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/brooksmatelski-fig2-768x595.jpg 768w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/brooksmatelski-fig2-1536x1190.jpg 1536w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/brooksmatelski-fig2-2048x1587.jpg 2048w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/brooksmatelski-fig2-1200x930.jpg 1200w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2020\/06\/brooksmatelski-fig2-1980x1534.jpg 1980w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>figure 2 (original caption &#8220;<em>The set of C&#8217;s such that f(z) = z\u00b2 + C has a stable periodic orbit<\/em>&#8220;\u009d) from Brooks, Robert, and J. Peter Matelski. &#8220;<a href=\"http:\/\/abel.math.harvard.edu\/archive\/118r_spring_05\/docs\/brooksmatelski.pdf\">The dynamics of 2-generator subgroups of PSL (2, C).<\/a>&#8221; <em>Riemann surfaces and related topics: Proceedings of the 1978 Stony Brook Conference, Ann. of Math. Stud<\/em>. Vol. 97. 1981.<\/figcaption><\/figure>\n\n\n\n<p>What I&#8217;ve done &#8211; and mostly thanks to tweaks by commenter <em>nobody<\/em> below &#8211; is create period-appropriate code to reproduce that graphic. Since the paper was presented in 1978, there&#8217;s a fair chance that  the authors had access to a machine running FORTRAN-77 or a near equivalent. FORTRAN&#8217;s particularly good for this:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>it has a built-in COMPLEX type that extends regular mathematical functions;<\/li><li>it has <em>just<\/em> good enough string handling to output a line of spaces\/asterisks. I would not have wanted to write this in FORTRAN-66, as that language had no string manipulation facilities <span style=\"text-decoration: underline;\">at<\/span> <span style=\"text-decoration: underline;\">all<\/span>.<\/li><\/ul>\n\n\n\n<p>So here&#8217;s the code. It should compile on any Fortran compiler:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: plain; title: ; notranslate\" title=\"\">\n      PROGRAM BRKMTF\n!     GENERATE FIGURE FROM BROOKS-MATELSKI PAPER C.1978\n!     THAT EVENTUALLY BECAME KNOWN AS THE MANDELBROT SET\n!     - SCRUSS, 2022-05\n!     REF: BROOKS, ROBERT, AND J. PETER MATELSKI.\n!     &quot;THE DYNAMICS OF 2-GENERATOR SUBGROUPS OF PSL (2, C).&quot;\n!     RIEMANN SURFACES AND RELATED TOPICS: PROCEEDINGS OF THE\n!     1978 STONY BROOK CONFERENCE,\n!     ANN. OF MATH. STUD. VOL. 97. 1981: FIG. 2, P. 81\n\n      REAL MAP, CR, CI\n      INTEGER I, J, K, M, ROWS, COLS, MAXIT\n      COMPLEX C, Z\n      PARAMETER (ROWS=31, COLS=71, MAXIT=200)\n      CHARACTER*80 OUT\n      CHARACTER CH*1\n\n      DO J=1,ROWS\n         CI=MAP(REAL(J), 1.0, REAL(ROWS), -0.8715, 0.8715)\n         DO I=1,COLS\n            CR=MAP(REAL(I), 1.0, REAL(COLS), -1.975, 0.475)\n            C=CMPLX(CR, CI)\n            Z=CMPLX(0.0, 0.0)\n            CH=&#039;*&#039;\n            DO 100, K=1,MAXIT\n               Z = Z**2 + C\n               IF (ABS(Z) .GT. 2) THEN\n                  CH=&#039; &#039;\n                  GO TO 101\n               END IF\n 100        CONTINUE\n 101        OUT(I:I)=CH\n         END DO\n         WRITE(*,*)OUT\n      END DO\n      END\n\n      REAL FUNCTION MAP(X, XMIN, XMAX, YMIN, YMAX)\n      REAL X, XMIN, XMAX, YMIN, YMAX\n      MAP = YMIN + (YMAX - YMIN) * ((X - XMIN) \/ (XMAX - XMIN))\n      END\n<\/pre><\/div>\n\n\n<p>The results are spot-on:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"478\" height=\"399\" src=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2022\/05\/brkmtf.png\" alt=\"mandelbrot set, rendered in asterisks from BRKMTF.F\" class=\"wp-image-17021\" srcset=\"https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2022\/05\/brkmtf.png 478w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2022\/05\/brkmtf-320x267.png 320w, https:\/\/scruss.com\/wordpress\/wp-content\/uploads\/2022\/05\/brkmtf-160x134.png 160w\" sizes=\"auto, (max-width: 478px) 100vw, 478px\" \/><figcaption>party like it&#8217;s &#8217;78<\/figcaption><\/figure>\n\n\n\n<p>Maybe Brooks &amp; Matelski had access to an Apple II and wrote something in BASIC? I could be entirely period-accurate and write something in PDP-8 BASIC on my SBC6120, but not today.<\/p>\n\n\n\n<p>It really is much easier using a language with complex number support when working with the Mandelbrot set. Here&#8217;s the same program in Python3, which bears more of a resemblance to FORTRAN-77 than it might admit:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: python; title: ; notranslate\" title=\"\">\n#!\/usr\/bin\/python3\n# brkmtf - Brooks-Matelski proto ASCII Mandelbrot set - scruss, 2022-05\n# -*- coding: utf-8 -*-\n\ndef valmap(value, istart, istop, ostart, ostop):\n    return ostart + (ostop - ostart) * ((value - istart) \/ (istop - istart))\n\nrows = 31\ncols = 71\nmaxit = 200\n\nfor y in range(rows):\n    ci = valmap(float(y + 1), 1.0, float(rows), -0.8715, 0.8715)\n    for x in range(cols):\n        cr = valmap(float(x + 1), 1.0, float(cols), -1.975, 0.475)\n        c = complex(cr, ci)\n        z = complex(0.0, 0.0)\n        ch = &#039;*&#039;\n        for k in range(maxit):\n            z = z**2 + c\n            if (abs(z) &gt; 2.0):\n                ch = &#039; &#039;\n                break\n        print(ch, end=&#039;&#039;)\n    print()\n\n<\/pre><\/div>\n\n\n<p>I found out about the Brooks-Matelski paper from this article: <a href=\"https:\/\/www.scientificamerican.com\/article\/mandelbrot-set-1990-horgan\/\">Who Discovered the Mandelbrot Set? &#8211; Scientific American<\/a>. It&#8217;s none too complimentary towards Benoit Mandelbrot.<\/p>\n\n\n\n<p><strong>Update<\/strong>: see the <a href=\"#comment-1279871\">comment from one of the authors of the original paper below<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How many CPU hours did I burn in the early 1990s rendering bits of the Mandelbrot Set? A lot, mainly because I was doing it in BASIC on an unexpanded 8 MHz Commodore Amiga A500. The image below that Fraqtive rendered in almost no time would have taken me days: But it turns out that [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[2],"tags":[],"class_list":["post-16349","post","type-post","status-publish","format-standard","hentry","category-goatee-stroking-musing-or-something"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pQNZZ-4fH","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/16349","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/comments?post=16349"}],"version-history":[{"count":8,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/16349\/revisions"}],"predecessor-version":[{"id":17063,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/posts\/16349\/revisions\/17063"}],"wp:attachment":[{"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/media?parent=16349"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/categories?post=16349"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/scruss.com\/blog\/wp-json\/wp\/v2\/tags?post=16349"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}