I wasn't aiming for speed - it's never going to be fast in BASIC, but I wanted to change the ASCII 'palette' and make sure it would run in as many BASICs I had to hand, so 2-character variable names, one statement per line. It won't run un-changed in my RTB, but that's not really important here, although note that RTB doesn't support multiple statements per line as there is no performance overhead to be gained in it from that trick.
There are 3 versions of the 6502 based BBC Basic, all from 1981 to 1983 and a 65C02 version in 1984 which was intended for the 65C02 2nd processor. I can run any of these on Ruby.
The results are not surprising: ehBasic is the slowest, Applesoft marginally faster, BBC Basic 4 (the 65C02 version) almost double the speed of ehBasic. For the parameters I used:
- ehBasic: 172 seconds
- Applesoft: 161 seconds
- BBC Basic 1-3: 124 seconds
- BBC Basic 4: 96 seconds
Code: Select all
100 REM A BASIC, ASCII MANDELBROT
110 REM
120 REM This implementation copyright (c) 2019, Gordon Henderson
130 REM
140 REM Permission to use/abuse anywhere for any purpose granted, but
150 REM it comes with no warranty whatsoever. Good luck!
160 REM
170 C$ = ".,'~=+:;[/<&?oxOX# " : REM 'Pallet' Lightest to darkest...
180 SO = 1 : REM Set to 0 if your MID$() indexes from 0.
190 MI = LEN(C$)
200 MX = 4
210 LS = -2.0
220 TP = 1.25
230 XS = 2.5
240 YS = -2.5
250 W = 64
260 H = 48
270 SX = XS / W
280 SY = YS / H
290 Q = TIME
300 FOR Y = 0 TO H
310 CY = Y * SY + TP
320 FOR X = 0 TO W
330 CX = X * SX + LS
340 ZX = 0
350 ZY = 0
360 CC = SO
370 X2 = ZX * ZX
380 Y2 = ZY * ZY
390 IF CC > MI THEN GOTO 460
400 IF (X2 + Y2) > MX THEN GOTO 460
410 T = X2 - Y2 + CX
420 ZY = 2 * ZX * ZY + CY
430 ZX = T
440 CC = CC + 1
450 GOTO 370
460 PRINT MID$(C$, CC - SO, 1);
470 NEXT
480 PRINT
490 NEXT
500 PRINT
510 PRINT (TIME - Q) / 100
520 END
(And FWIW: While not a fair comparison by any standards, RTB on my Intel i3 desktop produces a 16-colour version in 640x480 graphics in 1.2 seconds...)
You can change the LS (Left Side) and TP (Top) to change the start location if you want to play with zooming in.
Here is the output:
Code: Select all
............,,,,,,,,,,,,,,'''''''''''''''''''''''''',,,,,,,,,,,,,
...........,,,,,,,,,,,''''''''''''''''''''''''''''''''',,,,,,,,,,
..........,,,,,,,,,'''''''''''''''''''''''~~~~===~~~~''''',,,,,,,
.........,,,,,,,,'''''''''''''''''''''~~~~~~=+[&+==~~~~~''''',,,,
........,,,,,,,'''''''''''''''''''''~~~~~~~==+: ;+++~~~~~~''''',,
.......,,,,,,'''''''''''''''''''''~~~~~~~~===+:[ / [+~~~~~~''''''
......,,,,,,''''''''''''''''''''~~~~~~~~~===+:;/?o[:+==~~~~~'''''
......,,,,''''''''''''''''''''~~~~~~~~~====+:O/x <;:+==~~~~~~'''
.....,,,,''''''''''''''''''''~~~~~~~~~===++:# X/+====~~~~'''
.....,,,'''''''''''''''''''~~~~~~~~~==++++:;/X [:++====~~~''
....,,,'''''''''''''''''''~~~~~~~~==+++:::;[/ X/;:+++++==~~'
....,,''''''''''''''''''~~~~~~~===+[<&x[[? <&x o&//<;:::[[=~~
...,,'''''''''''''''''~~~~~~=====+:; &O /[</&/:=~
...,'''''''''''''''''~~~========++:;< x :=~
..,,'''''''''''''''~~=========+++:;/<O ;+==
..,'''''''''''''~~~=========++++:< ## X<;:+=
..''''''''''~~~~==:/++++++++::::;/x [;:=
.,''''''~~~~~~===+:X[;:;; ;;::;;[ o/=
.,''''~~~~~~~===++;<xXo<<X &<[[[/ X:+
.'''~~~~~~~=====+::[& <<& /:=
.'~~~~~~~~=====+::;/? oO :=
.'~~~~~~~====++/;[/o [+=
.~~~~~~=++++::;/???X #:+=
.==++:/::+:;;[[o :+==
&[:+==
.==++:/::+:;;[[o :+==
.~~~~~~=++++::;/???X #:+=
.'~~~~~~~====++/;[/o [+=
.'~~~~~~~~=====+::;/? oO :=
.'''~~~~~~~=====+::[& <<& /:=
.,''''~~~~~~~===++;<xXo<<X &<[[[/ X:+
.,''''''~~~~~~===+:X[;:;; ;;::;;[ o/=
..''''''''''~~~~==:/++++++++::::;/x [;:=
..,'''''''''''''~~~=========++++:< ## X<;:+=
..,,'''''''''''''''~~=========+++:;/<O ;+==
...,'''''''''''''''''~~~========++:;< x :=~
...,,'''''''''''''''''~~~~~~=====+:; &O /[</&/:=~
....,,''''''''''''''''''~~~~~~~===+[<&x[[? <&x o&//<;:::[[=~~
....,,,'''''''''''''''''''~~~~~~~~==+++:::;[/ X/;:+++++==~~'
.....,,,'''''''''''''''''''~~~~~~~~~==++++:;/X [:++====~~~''
.....,,,,''''''''''''''''''''~~~~~~~~~===++:# X/+====~~~~'''
......,,,,''''''''''''''''''''~~~~~~~~~====+:O/x <;:+==~~~~~~'''
......,,,,,,''''''''''''''''''''~~~~~~~~~===+:;/?o[:+==~~~~~'''''
.......,,,,,,'''''''''''''''''''''~~~~~~~~===+:[ / [+~~~~~~''''''
........,,,,,,,'''''''''''''''''''''~~~~~~~==+: ;+++~~~~~~''''',,
.........,,,,,,,,'''''''''''''''''''''~~~~~~=+[&+==~~~~~''''',,,,
..........,,,,,,,,,'''''''''''''''''''''''~~~~===~~~~''''',,,,,,,
...........,,,,,,,,,,,''''''''''''''''''''''''''''''''',,,,,,,,,,
............,,,,,,,,,,,,,,'''''''''''''''''''''''''',,,,,,,,,,,,,
Extracting the BBC Basic floating point routines may be an interesting exercise at some point if I need faster FP routines. It's a 5 byte format though.
Cheers,
-Gordon