Categories
goatee-stroking musing, or something

The Mandelbrot Set, before Mandelbrot

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:

the squashed bug that started it all: the Mandelbrot set

But it turns out that the first rendering of what we now call the Mandelbrot set wasn’t produced by Benoit Mandelbrot, but by Brooks & Matelski a year or two earlier:

text plot of the Mandelbrot set with points inside set marked with asterisks
figure 2 (original caption “The set of C’s such that f(z) = z² + C has a stable periodic orbit”) from Brooks, Robert, and J. Peter Matelski. “The dynamics of 2-generator subgroups of PSL (2, C).Riemann surfaces and related topics: Proceedings of the 1978 Stony Brook Conference, Ann. of Math. Stud. Vol. 97. 1981.

What I’ve tried to do — and come close, but not actually managed to exactly replicate — is create period-appropriate code to reproduce that graphic. Since the paper was presented in 1978, there’s a fair chance that the authors had access to a machine running FORTRAN-77 or a near equivalent. FORTRAN’s particularly good for this:

  • it has a built-in COMPLEX type that extends regular mathematical functions;
  • it has just 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 at all.

So here’s the code. It should compile on any Fortran compiler:

      PROGRAM BRKMAT
! GENERATE FIGURE FROM BROOKS-MATELSKI PAPER C.1978
!  THAT EVENTUALLY BECAME KNOWN AS THE MANDELBROT SET
! - SCRUSS, 2020-06
! REF: BROOKS, ROBERT, AND J. PETER MATELSKI.
!     "THE DYNAMICS OF 2-GENERATOR SUBGROUPS OF PSL (2, C)."
!      RIEMANN SURFACES AND RELATED TOPICS: PROCEEDINGS OF THE
!      1978 STONY BROOK CONFERENCE,
!      ANN. OF MATH. STUD. VOL. 97. 1981: FIG. 2, P. 81

         REAL MAP, CR, CI
         INTEGER I, J, K, M, ROWS, COLS, MAXIT
         COMPLEX C, Z
         PARAMETER (ROWS=31, COLS=70, MAXIT=36)
         CHARACTER*80 OUT
         CHARACTER CH*1

         DO J=1,ROWS
            CI=MAP(REAL(J), 1.0, REAL(ROWS), -0.89, 0.89)
            DO I=1,COLS
               CR=MAP(REAL(I), 1.0, REAL(COLS), -2.0, 0.45)
               C=CMPLX(CR, CI)
               Z=CMPLX(0.0, 0.0)
               CH='*'
               DO 100, K=1,MAXIT
                  Z = Z**2 + C
                  IF (ABS(Z) .GT. 2) THEN
                     CH=' '
                     GO TO 101
                  END IF
 100           CONTINUE
 101           OUT(I:I)=CH
            END DO
            WRITE(*,*)OUT
         END DO
      END

      REAL FUNCTION MAP(X, XMIN, XMAX, YMIN, YMAX)
         REAL X, XMIN, XMAX, YMIN, YMAX
         MAP = YMIN + (YMAX - YMIN) * ((X - XMIN) / (XMAX - XMIN))
      END

The results are close:

mandelbrot set, rendered in asterisks from BRKMAT.F
a few more holes in this than the original

but not quite right. Maybe Brooks & 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.

It really is much easier using a language with complex number support when working with the Mandelbrot set. Here’s the same program in Python3, which bears more of a resemblance to FORTRAN-77 than it might admit:

#!/usr/bin/python3
# brkmat - Brooks-Matelski proto ASCII Mandelbrot set - scruss, 2020-06
# -*- coding: utf-8 -*-

def valmap(value, istart, istop, ostart, ostop):
    return ostart + (ostop - ostart) * ((value - istart) / (istop - istart))

rows = 31
cols = 70
maxit = 36

for y in range(rows):
    ci = valmap(float(y + 1), 1.0, float(rows), -0.89, 0.89)
    for x in range(cols):
        cr = valmap(float(x + 1), 1.0, float(cols), -2.0, 0.45)
        c = complex(cr, ci)
        z = complex(0.0, 0.0)
        ch = '*'
        for k in range(maxit):
            z = z**2 + c
            if (abs(z) > 2.0):
                ch = ' '
                break
        print(ch, end='')
    print()

I found out about the Brooks-Matelski paper from this article: Who Discovered the Mandelbrot Set? – Scientific American. It’s none too complimentary towards Benoit Mandelbrot.

Categories
computers suck

yet another homage …

So it turns out that Mines Incas is yet another variant on 2D Star Dodge / Asterisk Tracker theme. And it’s really well done!

Play it in your browser: Mines Incas

Info page at CPC-POWER: Mines Incas

Categories
goatee-stroking musing, or something

MicroPython on the BrainPad Classic/BP2

GHI Electronics BrainPad Classic/BP2 electronics project board on a tasteful faux-leopard background. Small OLED screen is showing "SCRUSS 2020"
GHI Electronics BrainPad Classic/BP2 in 3d printed case

I’ve extended the MicroPython examples for the BrainPad Classic so that all of the devices work: scruss/brainpad-micropython: Micropython examples for the BrainPad Classic (BP2) from GHI Electronics.

The ones that already worked in the original examples repo are:

  • buttons
  • accelerometer
  • LEDs
  • light sensor
  • OLED screen

I’ve added:

  • temperature sensor: although my calibration may be a bit off on the MCP9701a used on the board
  • timer blink example: STM32 Timers are cool and we should use them
  • PWM RGB LED example: floating-point silliness with HSV(ish) Colour Wheel in Python
  • buzzer: simple tones plus tunes (in RTTTL) via dhylands / upy-rtttl
  • servos: I may have forgotten to put the example in there, but the standard Servo(1) code should work.

Yes, it would be nice to have a slick unified library like the BBC micro:bit does. For later, though.

Other resources:

Categories
photo

godspeed, Edouard LeBlanc

godspeed, Edouard LeBlanc

Instagram filter used: Normal

View in Instagram ⇒

Categories
photo

mood

mood

Instagram filter used: Lo-fi

View in Instagram ⇒

Categories
photo

virtual potato print

virtual potato print

Instagram filter used: Normal

View in Instagram ⇒

Categories
photo

mornin’

mornin’

Instagram filter used: Lo-fi

View in Instagram ⇒

Categories
photo

groundhog!

nomming from our deck

Categories
goatee-stroking musing, or something

terminal colour silliness with Python

terminal text in rainbows

Using ansicolors:

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# colourshen.py - stdin to rainbow stdout
# scruss, 2020-06

from colors import *            # see https://pypi.org/project/ansicolors/
import sys
wheel_pos = 0


def cos_wheel(pos):
    # Input a value 0 to 255 to get a colour value.
    # scruss (Stewart Russell) - 2019-03 - CC-BY-SA
    from math import cos, pi
    if pos < 0:
        return (0, 0, 0)
    pos %= 256
    pos /= 255.0
    return (int(255 * (1 + cos(pos * 2 * pi)) / 2),
            int(255 * (1 + cos((pos - 1 / 3.0) * 2 * pi)) / 2),
            int(255 * (1 + cos((pos - 2 / 3.0) * 2 * pi)) / 2))


def hex_wheel(pos):
    rgb = cos_wheel(pos)
    return('#%02x%02x%02x' % rgb)


def wheel_print(s):
    global wheel_pos
    incr = int(256/(1+len(s)))-1
    if incr < 1:
        incr = 1
    for c in s:
        print(color(c, fg=hex_wheel(wheel_pos)), end='')
        wheel_pos = (wheel_pos+incr) % 256
    print()


for txt in sys.stdin:
    wheel_print(txt.rstrip())

(fixed a very obvious ahem! in the code, hope no-one noticed …)

Categories
photo

groundhog helps with the pruning

groundhog helps with the pruning

Instagram filter used: Normal

View in Instagram ⇒

groundhog helps with the pruning
Categories
photo

MÖNCH

MÖNCH

Instagram filter used: Normal

View in Instagram ⇒

Categories
goatee-stroking musing, or something

mandala with chips

8-way symmetric constructed mandala on a black background with small unencapsulated silicon chips placed as jewels every 45°
graphite, pencil crayons, silicon chips
small rectangular silicon chip sitting on gold graphite background
detail at 600 dpi. I have lots of these.
Categories
photo

fortran made a stripey one

fortran made a stripey one

Instagram filter used: Normal

View in Instagram ⇒

Categories
photo

chips with everything

chips with everything

Instagram filter used: Normal

View in Instagram ⇒

Categories
choons

Röhrensound

Categories
computers suck

“No Yoda Printing Here”

Thingiverse link: https://www.thingiverse.com/thing:4426514

Categories
photo

we’re in for some weather

we’re in for some weather

Instagram filter used: Lo-fi

View in Instagram ⇒

Categories
photo

tongue elaters

tongue elaters

Instagram filter used: Lo-fi

View in Instagram ⇒

Categories
photo

Dang: broken rail on my Brooks saddle

Dang: broken rail on my Brooks saddle

Instagram filter used: Lo-fi

View in Instagram ⇒

Categories
photo

seemed like a good idea at the time

seemed like a good idea at the time

Instagram filter used: Lo-fi

View in Instagram ⇒