Mandelbrot v1 for Amiga in C |
| This is the C version of the Mandelbrot v1 program, originally written in assembler. It is provided here for comparison. It produces exactly the same picture as the ASM version, and the functions correspond directly to those described in the assembler version.
The only difference is that a small optimization - multiplying by 2.0 - is not used in the outermost loop of the calculation, as it would only make the C source harder to read and bring very limited benefit (as seen on the line 069). On the other hand, in the innermost loop it brings a significant benefit,
as it eliminates one of four multiplications. The implementation of this optimization can be found lines 063 and 082. The principle is explained in the ASM source description. The program was compiled using SAS/C 5.10. It should be compiled like this (content of CMandelbrot_v1.build file): LC -b1 -cfist -ff -O -v -y CMandelbrot_V1.c The C source for SAS/C 5.10, the build script, the Amiga executable, and the icons (from SAS/C) can be downloaded here. |
001 #define APP_WIDTH 320 002 #define APP_HEIGHT 121 003 #define MAX_ITER 75 004 005 #include <exec/types.h> 006 #include <exec/ports.h> 007 #include <graphics/rastport.h> 008 #include <graphics/gfxbase.h> 009 #include <intuition/intuitionbase.h> 010 #include <libraries/dos.h> 011 #include <proto/all.h> 012 013 struct GfxBase *GfxBase = NULL; 014 struct IntuitionBase *IntuitionBase = NULL; 015 016 struct Window *window = NULL; 017 struct RastPort *rastport; 018 USHORT borderleft, bordertop; 019 020 int GetReplyMsg(void) 021 { 022 struct IntuiMessage *intuiMessage; 023 024 intuiMessage = (struct IntuiMessage *)GetMsg(window->UserPort); 025 if (intuiMessage) 026 ReplyMsg((struct Message *)intuiMessage); 027 028 return (int)intuiMessage; 029 } 030 031 void ExecWait(void) 032 { 033 Wait(1 << window->UserPort->mp_SigBit); 034 GetReplyMsg(); 035 } 036 037 struct NewWindow nw = 038 { 039 100, 20, APP_WIDTH, APP_HEIGHT, -1, -1, CLOSEWINDOW | NEWSIZE, 040 WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE | SMART_REFRESH | ACTIVATE, 041 NULL, NULL, "CMandelbrot v1", NULL, NULL, 100, 20, 640, 200, 042 WBENCHSCREEN 043 }; 044 045 USHORT GetPointColor(USHORT iter) 046 { 047 if (iter == MAX_ITER) 048 return 0; 049 050 return iter % 3 + 1; 051 } 052 053 void DrawPoint(USHORT x, USHORT y, USHORT color) 054 { 055 SetAPen(rastport, color); 056 WritePixel(rastport, x + borderleft, y + bordertop); 057 } 058 059 void CalcMandelbrot(void) 060 { 061 float xstep, cr, ci, zr, zi, zr2, zi2; 062 USHORT pos_x, pos_y, iter; 063 UBYTE *p_zr = ((UBYTE *) &zr) + 3; /* pointer to the exponent of zr */ 064 065 xstep = 3.0 / (float)APP_WIDTH; 066 067 for (pos_y = 0; pos_y < APP_HEIGHT; pos_y++) 068 { 069 ci = 2.0 * pos_y * xstep - 1.125; /* optimization is not used here */ 070 for (pos_x = 0; pos_x < APP_WIDTH; pos_x++) 071 { 072 cr = pos_x * xstep - 2.25; 073 074 iter = 1; 075 zr = cr; 076 zi = ci; 077 do 078 { 079 zr2 = zr * zr; 080 zi2 = zi * zi; 081 if (zr2 + zi2 >= 4.0) break; 082 (*p_zr)++; /* zr *= 2.0; */ 083 zi = zr * zi + ci; 084 zr = zr2 - zi2 + cr; 085 iter++; 086 } while (iter != MAX_ITER); 087 DrawPoint(pos_x, pos_y, GetPointColor(iter)); 088 if (GetReplyMsg()) return; 089 } 090 } 091 ExecWait(); 092 } 093 094 int main(int argc, char *argv[]) 095 { 096 int exitval = RETURN_ERROR; 097 098 IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 099 0L); 100 if (!IntuitionBase) goto fini; 101 102 GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0L); 103 if (!GfxBase) goto fini; 104 105 window = OpenWindow(&nw); 106 if (!window) goto fini; 107 108 exitval = RETURN_OK; 109 110 borderleft = window->BorderLeft; 111 bordertop = window->BorderTop; 112 rastport = window->RPort; 113 SizeWindow(window, borderleft + window->BorderRight, 114 bordertop + window->BorderBottom); 115 ExecWait(); 116 117 CalcMandelbrot(); 118 119 fini: 120 if (window) CloseWindow(window); 121 if (IntuitionBase) CloseLibrary((struct Library *)IntuitionBase); 122 if (GfxBase) CloseLibrary((struct Library *)GfxBase); 123 124 return exitval; 125 } |