![]() |
Forum Index : Microcontroller and PC projects : CMM2 :mandlebrot CSUB
Page 1 of 2 ![]() ![]() |
|||||
Author | Message | ||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10068 |
Takes 1.6 seconds to run 800x600 Video ![]() mandelbrot 64 'parameter is the maximum number of iterations do:loop CSUB mandelbrot 00000000 B097B590 6078AF00 0200F04F E9C74B96 F44F230C 62FB7348 7316F44F 230062BB 2300627B 230163BB E10963FB 643B2301 6C3BE0FE 3A90EE07 6AE7EEF8 EE076AFB EEB83A90 EEC67AE7 EEB77A87 EEB67AE7 EE376B00 ED975B46 EE856B0C EEB07B06 EE276B08 ED9F7B06 EE376B7C ED877B46 6BFB7B06 3A90EE07 6AE7EEF8 EE076ABB EEB83A90 EEC67AE7 EEB77A87 EEB67AE7 EE376B00 ED975B46 EE856B0C EEB07B06 EE276B08 ED877B06 F04F7B04 F04F0200 E9C70300 F04F2314 F04F0200 E9C70300 23012312 E039647B 7B14ED97 6B07EE27 7B12ED97 7B07EE27 7B47EE36 6B06ED97 7B07EE36 7B02ED87 7B14ED97 6B07EE37 7B12ED97 7B07EE26 6B04ED97 7B07EE36 7B12ED87 2302E9D7 2314E9C7 7B14ED97 6B07EE27 7B12ED97 7B07EE27 7B07EE36 6B00EEB1 7BC6EEB4 FA10EEF1 6C7BDD03 4B4E63BB 6C7B647B 647B3301 681B687B 429A6C7A 687BDBC0 6C7A681B D109429A 681B4B47 6C3B461C 22003B01 46186BF9 E06247A0 EE076BBB EEB83A90 ED9F7BE7 EE276B3C EEFD7B06 EE177BC7 425A3A90 B2D2B2DB 4253BF58 6BBB627B F003425A F0020303 BF580203 2B014253 4B34D10B 461C681B 1E586C3B 4B326A7A 461A4313 47A06BF9 6BBBE039 F003425A F0020303 BF580203 2B024253 4B29D10B 461C681B 1E586C3B F4436A7B 461A037F 47A06BF9 6BBBE023 F003425A F0020303 BF580203 2B034253 4B1ED10B 461C681B 1E586C3B F4436A7B 461A437F 47A06BF9 6BBBE00D 0303F003 D1082B00 681B4B15 6C3B461C 6A7A3B01 46186BF9 6C3B47A0 643B3301 6AFB6C3A F77F429A 6BFBAEFC 63FB3301 6ABB6BFA F77F429A BF00AEF1 375CBF00 BD9046BD 8000F3AF 66666666 3FE66666 00000000 40A0B200 3FF00000 000F423F 08000338 00FFFF00 End CSUB #include "ARMCFunctions.h" void mandelbrot(int *itermax){ double x,xx,y,cx,cy; int iteration,hx,hy; double magnify=1.0; /* no magnification */ int hxres = 800; /* horizonal resolution */ int hyres = 600; /* vertical resolution */ int lastiter=0, theiter=0; for (hy=1;hy<=hyres;hy++) { for (hx=1;hx<=hxres;hx++) { cx = (((float)hx)/((float)hxres)-0.5)/magnify*3.0-0.7; cy = (((float)hy)/((float)hyres)-0.5)/magnify*3.0; x = 0.0; y = 0.0; for (iteration=1;iteration<*itermax;iteration++) { xx = x*x-y*y+cx; y = 2.0*x*y+cy; x = xx; if (x*x+y*y > 4.0){ theiter=iteration; iteration = 999999; } } if (iteration== *itermax) DrawPixel(hx-1,hy,0x00); else { lastiter=((int)((MMFLOAT)theiter * 2137.0)) % 256; if(theiter% 4==1)DrawPixel(hx-1,hy,0xFFFF00 | lastiter ); else if(theiter% 4==2)DrawPixel(hx-1,hy,0xFF0000 | lastiter ); else if(theiter% 4==3)DrawPixel(hx-1,hy,0xFF00 | lastiter ); else if(theiter% 4==0)DrawPixel(hx-1,hy, lastiter ); } } } } Edited 2020-07-07 23:57 by matherp |
||||
thwill![]() Guru ![]() Joined: 16/09/2019 Location: United KingdomPosts: 4251 |
Very impressive. Thank you again for adding CSUB support. Regards, Tom MMBasic for Linux, Game*Mite, CMM2 Welcome Tape, Creaky old text adventures |
||||
daveculp Newbie ![]() Joined: 02/07/2020 Location: United StatesPosts: 22 |
I had NO idea it was possible to do this on the CMM2. This changes everything! One of the first things I did was write a Mandelbrot plotter and mine works, but it is 10X slower at least as it is in 100% BASIC. I also wrote a Conways Game of Life implementation and it works but once again, being 100% BASIC, it is slow. So, exactlly how does this work, is there are tutorial or info as there is nothing in the user manual. Thanks! |
||||
lizby Guru ![]() Joined: 17/05/2016 Location: United StatesPosts: 3314 |
CMM2 CSUBs PicoMite, Armmite F4, SensorKits, MMBasic Hardware, Games, etc. on fruitoftheshed |
||||
abraxas Regular Member ![]() Joined: 16/06/2020 Location: CanadaPosts: 99 |
What would be really nice is for someone to write Pete's code in pure MMBasic so we would have an apples-to-apple comparison of number cruching performance of CSUBs vs plain BASIC subs. |
||||
daveculp Newbie ![]() Joined: 02/07/2020 Location: United StatesPosts: 22 |
My implementation in pure MMBASIC is very similar, I will post it later. It is MUCH, MUCH slower. Edited 2020-07-08 07:11 by daveculp |
||||
Sasquatch![]() Guru ![]() Joined: 08/05/2020 Location: United StatesPosts: 376 |
I took the liberty of tweaking Peters Mandelbrot CSub. It now accepts scale and position coordinates. I also inverted the Y display coordinates to be more standard. It's still pretty darn fast! Edit: You will need one of the latest beta versions of MMBasic to run this! If someone wants to write a MMBasic UI to make it interactive that would be awesome. I will get to it "someday" if nobody else volunteers! The coordinate system looks like this: ![]() Here is the MMBasic Code: mode 1,8 T = Timer 'Mandelbrot(Depth,Scale,XCenter,YCenter) 'Depth is int, all others float Mandelbrot 255,1.0,-0.75,0.0 Print Timer-T Do While Inkey$ = "" : Loop 'File Mandelbrot.bas written 07-07-2020 14:38:26 'Mandelbrot CSub 'Mandelbrot(Depth,Scale,XCenter,YCenter) CSUB Mandelbrot 00000000 B097B590 60F8AF00 607A60B9 4BA0603B 681B681B 4B9F637B 681B681B 2300633B 230062FB 230163BB E12363FB 643B2301 6C3BE118 3A90EE07 6AE7EEF8 EE076B7B EEB83A90 EEC67AE7 EEB77A87 EEB67AE7 EE376B00 68BB5B46 7A00EDD3 6AE7EEB7 7B06EE85 6B08EEB0 6B06EE27 EDD3687B EEB77A00 EE367AE7 ED877B07 6BFB7B08 3A90EE07 6AE7EEF8 EE076B3B EEB83A90 EEC67AE7 EEB77A87 EEB67AE7 EE376B00 68BB5B46 7A00EDD3 6AE7EEB7 7B06EE85 6B08EEB0 6B06EE27 EDD3683B EEB77A00 EE367AE7 ED877B07 F04F7B06 F04F0200 E9C70300 F04F2314 F04F0200 E9C70300 23012312 E039647B 7B14ED97 6B07EE27 7B12ED97 7B07EE27 7B47EE36 6B08ED97 7B07EE36 7B04ED87 7B14ED97 6B07EE37 7B12ED97 7B07EE26 6B06ED97 7B07EE36 7B12ED87 2304E9D7 2314E9C7 7B14ED97 6B07EE27 7B12ED97 7B07EE27 7B07EE36 6B00EEB1 7BC6EEB4 FA10EEF1 6C7BDD03 4B5163BB 6C7B647B 647B3301 681B68FB 429A6C7A 68FBDBC0 6C7A681B D10B429A 681B4B4A 6C3B461C 6B3A1E58 1AD36BFB 46192200 E06A47A0 EE076BBB EEB83A90 ED9F7BE7 EE276B3D EEFD7B06 EE177BC7 425A3A90 B2D2B2DB 4253BF58 6BBB62FB F003425A F0020303 BF580203 2B014253 4B36D10D 461C681B 1E586C3B 6BFB6B3A 6AFA1AD1 43134B32 47A0461A 6BBBE03F F003425A F0020303 BF580203 2B024253 4B2AD10D 461C681B 1E586C3B 6BFB6B3A 6AFB1AD1 037FF443 47A0461A 6BBBE027 F003425A F0020303 BF580203 2B034253 4B1ED10D 461C681B 1E586C3B 6BFB6B3A 6AFB1AD1 437FF443 47A0461A 6BBBE00F 0303F003 D10A2B00 681B4B14 6C3B461C 6B3A1E58 1AD36BFB 46196AFA 6C3B47A0 643B3301 6B7B6C3A F77F429A 6BFBAEE2 63FB3301 6B3B6BFA F77F429A BF00AED7 375CBF00 BD9046BD 00000000 40A0B200 080002EC 080002F0 000F423F 08000338 00FFFF00 End CSUB Edited 2020-07-08 07:16 by Sasquatch -Carl |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10068 |
Can you post the C source. I just fixed a problem in literal floats and it has broken your program. Need to understand why |
||||
Sasquatch![]() Guru ![]() Joined: 08/05/2020 Location: United StatesPosts: 376 |
Here is the source I still want to have a look at the color scheme to see if it can be improved without slowing the rendering. #include "ARMCFunctions.h" void mandelbrot(int *itermax,float *magnify, float *xcenter, float *ycenter){ double x,xx,y,cx,cy; int iteration,hx,hy; // double magnify=1.0; int hxres = HRes; /* horizonal resolution */ int hyres = VRes; /* vertical resolution */ int lastiter=0, theiter=0; for (hy=1;hy<=hyres;hy++) { for (hx=1;hx<=hxres;hx++) { cx = (((float)hx)/((float)hxres)-0.5)/ *magnify * 3.0 + *xcenter; cy = (((float)hy)/((float)hyres)-0.5)/ *magnify * 3.0 + *ycenter; x = 0.0; y = 0.0; for (iteration=1;iteration<*itermax;iteration++) { xx = x*x-y*y+cx; y = 2.0*x*y+cy; x = xx; if (x*x+y*y > 4.0){ theiter=iteration; iteration = 999999; } } if (iteration== *itermax) DrawPixel(hx-1,hyres - hy,0x00); else { lastiter=((int)((MMFLOAT)theiter * 2137.0)) % 256; if(theiter% 4==1)DrawPixel(hx-1,hyres - hy,0xFFFF00 | lastiter ); else if(theiter% 4==2)DrawPixel(hx-1,hyres - hy,0xFF0000 | lastiter ); else if(theiter% 4==3)DrawPixel(hx-1,hyres - hy,0xFF00 | lastiter ); else if(theiter% 4==0)DrawPixel(hx-1,hyres - hy, lastiter ); } } } } -Carl |
||||
abraxas Regular Member ![]() Joined: 16/06/2020 Location: CanadaPosts: 99 |
Pete, Do you envision in the future adding the ability for us to have CSUB code embedded right in the .bas file or at least in a separate .c file so that we could use them while remaining on CMM2? I'm shying away from CSUBs for the time being as I don't feel like doing the cross-compile and bytecode generation on a PC. It kind of saps some joy out of using the Maximite when all these steps are involved on a separate computer. |
||||
Sasquatch![]() Guru ![]() Joined: 08/05/2020 Location: United StatesPosts: 376 |
Did some more testing with the mandelbrot CSub. Seems calling the CSub with a variable for Depth (integer first parameter) works ok, but the other parameters don't seem to work with variables. This might be what Peter is already looking into? -Carl |
||||
Sasquatch![]() Guru ![]() Joined: 08/05/2020 Location: United StatesPosts: 376 |
Here is an example screen dump. As you can see in the uper left hand corner, it took 3.6seconds to render at 800X600. Depth = 64 Scale = 50.0 XCenter = 0.3935871840 YCenter = -0.1475255520 ![]() Edited 2020-07-08 08:59 by Sasquatch -Carl |
||||
Sasquatch![]() Guru ![]() Joined: 08/05/2020 Location: United StatesPosts: 376 |
Ok changing the data type of the float parameters to the MMFLOAT macro makes the CSub work with variables, now it won't work with constants, but I guess you can't have everything. Here is the new MMBasic example: Start: mode 1,8 Depth% = 64 Scale! = 50.0 XCenter! = 0.3935871840 YCenter! = -0.1475255520 T = Timer 'Mandelbrot(Depth,Scale,XCenter,YCenter) 'Depth is int all others float Mandelbrot Depth%,Scale!,XCenter!,YCenter! Print Timer-T 'Save Image "Mandelbrot.bmp" Do While Inkey$ = "" : Loop 'Mandelbrot CSub 'Mandelbrot(Depth,Scale,XCenter,YCenter) 'File Mandelbrot.bas written 07-07-2020 18:10:39 CSUB mandelbrot 00000000 B097B590 60F8AF00 607A60B9 4B9C603B 681B681B 4B9B637B 681B681B 2300633B 230062FB 230163BB E11B63FB 643B2301 6C3BE110 3A90EE07 6AE7EEF8 EE076B7B EEB83A90 EEC67AE7 EEB77A87 EEB67AE7 EE376B00 68BB5B46 6B00ED93 7B06EE85 6B08EEB0 6B06EE27 ED93687B EE367B00 ED877B07 6BFB7B08 3A90EE07 6AE7EEF8 EE076B3B EEB83A90 EEC67AE7 EEB77A87 EEB67AE7 EE376B00 68BB5B46 6B00ED93 7B06EE85 6B08EEB0 6B06EE27 ED93683B EE367B00 ED877B07 F04F7B06 F04F0200 E9C70300 F04F2314 F04F0200 E9C70300 23012312 E039647B 7B14ED97 6B07EE27 7B12ED97 7B07EE27 7B47EE36 6B08ED97 7B07EE36 7B04ED87 7B14ED97 6B07EE37 7B12ED97 7B07EE26 6B06ED97 7B07EE36 7B12ED87 2304E9D7 2314E9C7 7B14ED97 6B07EE27 7B12ED97 7B07EE27 7B07EE36 6B00EEB1 7BC6EEB4 FA10EEF1 6C7BDD03 4B5163BB 6C7B647B 647B3301 681B68FB 429A6C7A 68FBDBC0 6C7A681B D10B429A 681B4B4A 6C3B461C 6B3A1E58 1AD36BFB 46192200 E06A47A0 EE076BBB EEB83A90 ED9F7BE7 EE276B3D EEFD7B06 EE177BC7 425A3A90 B2D2B2DB 4253BF58 6BBB62FB F003425A F0020303 BF580203 2B014253 4B36D10D 461C681B 1E586C3B 6BFB6B3A 6AFA1AD1 43134B32 47A0461A 6BBBE03F F003425A F0020303 BF580203 2B024253 4B2AD10D 461C681B 1E586C3B 6BFB6B3A 6AFB1AD1 037FF443 47A0461A 6BBBE027 F003425A F0020303 BF580203 2B034253 4B1ED10D 461C681B 1E586C3B 6BFB6B3A 6AFB1AD1 437FF443 47A0461A 6BBBE00F 0303F003 D10A2B00 681B4B14 6C3B461C 6B3A1E58 1AD36BFB 46196AFA 6C3B47A0 643B3301 6B7B6C3A F77F429A 6BFBAEEA 63FB3301 6B3B6BFA F77F429A BF00AEDF 375CBF00 BD9046BD 00000000 40A0B200 080002EC 080002F0 000F423F 08000338 00FFFF00 End CSUB -Carl |
||||
Sasquatch![]() Guru ![]() Joined: 08/05/2020 Location: United StatesPosts: 376 |
So it would seem that with the parameters declared as *float passing literal constants works, and with the parameters declared as *MMFLOAT (basically a double) makes variables work. *Int seems to work for both variables and literal constants. Peter's original example renders in 1.9 seconds on a 400mHz CMM2 Here is the source that works with variables note that the only difference is in the mandelbrot function deceleration: #include "ARMCFunctions.h" void mandelbrot(int *itermax,MMFLOAT *magnify, MMFLOAT *xcenter, MMFLOAT *ycenter){ double x,xx,y,cx,cy; int iteration,hx,hy; // double magnify=1.0; int hxres = HRes; /* horizonal resolution */ int hyres = VRes; /* vertical resolution */ int lastiter=0, theiter=0; for (hy=1;hy<=hyres;hy++) { for (hx=1;hx<=hxres;hx++) { cx = (((float)hx)/((float)hxres)-0.5)/ *magnify * 3.0 + *xcenter; cy = (((float)hy)/((float)hyres)-0.5)/ *magnify * 3.0 + *ycenter; x = 0.0; y = 0.0; for (iteration=1;iteration<*itermax;iteration++) { xx = x*x-y*y+cx; y = 2.0*x*y+cy; x = xx; if (x*x+y*y > 4.0){ theiter=iteration; iteration = 999999; } } if (iteration== *itermax) DrawPixel(hx-1,hyres - hy,0x00); else { lastiter=((int)((MMFLOAT)theiter * 2137.0)) % 256; if(theiter% 4==1)DrawPixel(hx-1,hyres - hy,0xFFFF00 | lastiter ); else if(theiter% 4==2)DrawPixel(hx-1,hyres - hy,0xFF0000 | lastiter ); else if(theiter% 4==3)DrawPixel(hx-1,hyres - hy,0xFF00 | lastiter ); else if(theiter% 4==0)DrawPixel(hx-1,hyres - hy, lastiter ); } } } } Edited 2020-07-08 10:48 by Sasquatch -Carl |
||||
Sasquatch![]() Guru ![]() Joined: 08/05/2020 Location: United StatesPosts: 376 |
I originally tried using *double, but I was testing with literal constants and I couldn't get it to work. I then changed to *float and the literal constants worked but passing a variable wouldn't work. If you found a fix for the literal floats, chances are the latest version using the *MMFLOAT type should work for both? -Carl |
||||
daveculp Newbie ![]() Joined: 02/07/2020 Location: United StatesPosts: 22 |
Here is a pure MMBASIC implementation. Its slooooowwwwwww CLS black CONST w = MM.HRES CONST h = MM.VRES CONST maxi = 100 CONST colors = 65536 DIM sx AS FLOAT DIM x AS FLOAT DIM y AS FLOAT TIMER = 0 FOR py = 0 TO h - 1 REM Scale Y axis sy = (py / h) * 2 - 1 FOR px = 0 TO w - 1 REM Scale axis sx = (px / w) * 3.5 - 2.5 vy = 0 vx = 0 i = 0 x = 0 y = 0 do WHILE (x^2 + y^2 < 4) AND (i < maxi) xt = x^2 - y^2 + sx y = 2 * x * y + sy x = xt i = i + 1 loop c = i/maxi * colors pixel px, py, c NEXT px NEXT py PRINT TIMER "ms" SAVE IMAGE "mandel.bmp" Edited 2020-07-08 12:39 by daveculp |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10068 |
The fault in the current firmware is that you can only use simple floating point variables as parameters, not literals or functions returning a FP value. This will be fixed in the next release. No, simply impossible, as it would mean writing or porting a complete C compiler Edited 2020-07-08 18:15 by matherp |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 4854 |
Ported to BBC V basic running on the raspberry Pi zero. MODE 28 w = 800 h = 600 maxi = 64 TIME = 0 FOR py = 0 TO (h/2 - 1) sy = (py / h) * 2 - 1 FOR px = 0 TO w - 1 sx = (px / w) * 3.5 - 2.5 i = 0 x = 0 y = 0 WHILE ((x^2 + y^2 < 4) AND (i < maxi)) xt = x^2 - y^2 + sx y = 2 * x * y + sy x = xt i = i + 1 ENDWHILE GCOL i/maxi * 64 POINT px, py POINT px, h-py NEXT px NEXT py PRINT TIME*10 run time : 16 seconds (10x slower than the CMM2 CSUB) ![]() Edited 2020-07-08 20:36 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
Sasquatch![]() Guru ![]() Joined: 08/05/2020 Location: United StatesPosts: 376 |
Good work Daveculp and Volhout. The comparisons are quite interesting! Mandelbrot is kind of a special case as it uses tightly nested loops and lots of floating point math. It makes sense that eliminating the Basic parsing and using the fast math processor makes a huge difference! -Carl |
||||
Sasquatch![]() Guru ![]() Joined: 08/05/2020 Location: United StatesPosts: 376 |
Ok, I can't find a way to edit my older posts in this thread so I will put a warning here! Warning! Be warned that the MY original posts of MMBasic and C sourcecode for the Mandelbrot CSub are now Obsolete! Please use the latest versions in this thread! Edited 2020-07-09 00:18 by Sasquatch -Carl |
||||
Page 1 of 2 ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |