Front Ending C

by Randy Finch

As many of you know, C is a very good higher level language for writing speedy applications. Typically, however, there are just a few places within the program code where this speed is critical, i.e. important from the user perspective. Usually, handling input from the user through an application's interface is not one of these critical points. One then might ask, "Could I build the interface using an interactive authoring tool such as HELM or CanDo, write the speed critical parts in C, and then combine the two?" The logic behind this is that an interface is easier to build with an authoring tool than with C. Even if an interface creation tool kit that writes C code for you is used, it is sometimes confusing adding the event handling. In this article, I show you one way an authoring tool can be used to build a front end to a speed critical C application. There are not many applications that are as floating point math intensive as those that plot the Mandelbrot set and Julia sets. I wrote the core calculations for such an application in SAS/C 6.50 and then added a user interface designed in CanDo 2.51. To point out the speed advantages of writing the calculations in C as opposed to CanDo's scripting language, I have also written the calculations in CanDo so a speed comparison can be done.

The Mandelbrot Set and Julia Sets

For those of you unfamiliar with the Mandelbrot set and Julia sets (where have you been the last 10 years, under a rock?), I now give a brief explanation. The Mandelbrot set is a mathematical entity known as a fractal. It can be defined semi-formally as the set of all points, ci, in the complex plane such that the value of z in the iteration formula zn+1 = zn2 + ci remains bounded as n approaches infinity for an initial value of z (z0) of 0+0i. It can be shown that if the distance of z from the origin ever exceeds two, then the value of z approaches infinity as n approaches infinity and is therefore not bounded.

Julia sets are fractals also and are similar to the Mandelbrot set. However, there are an infinite number of Julia sets whereas there is only one Mandelbrot set. There is one Julia set for each value of ci in the complex plane. The Julia set for a particular value of ci is the set of all points, z, in the complex plane such that the value of z in the iteration formula zn+1 = zn2 + ci remains bounded as n approaches infinity. Well, so much for definitions. If you have seen any Mandelbrot or Julia set plots, you know that the points that make up the set are usually not the main point of interest; the points immediately surrounding the set are. Typically, the points belonging to the set are all one color and the points nearby are colored differently based on the number of iterations necessary to cause the distance of the point z from the origin to exceed two. This results in an image like that shown in Figure 1, which is the Mandelbrot set. Since the criteria for ceasing the iterations of the equation is that the distance of the point from the origin be greater than two, the image consists of a circle of radius two with inner distorted circles of decreasing radius. As the number of iterations approaches infinity, the distorted circles approach the shape of the outline of the Mandelbrot set. The same holds true for Julia sets. Of course, any program that actually carried the iterations to infinity would never end; therefore, a limit is specified. The number of iterations it takes to cause the distance of z from the origin to exceed two is known as the dwell of the point ci (z for a Julia set). The iteration limit is known as the maximum dwell or dwell limit. All points that allow the equation to be iterated the number of times specified by the maximum dwell are assumed to be a member of the Mandelbrot or Julia set being calculated. My program, CanDoMJ, allows the user to set the maximum dwell at either 15, 31, 63, or 127 via a menu selection. The larger this value is, the more accurate the plot will be but the longer it will take to calculate points close to and in the set. Let's now take a look at the CanDoMJ program. It is shown in Listing 1.

The CanDoMJ Deck

The CanDoMJ deck consists of two cards: MJSettings and MJPlotPic. The former is the main user interface where various settings related to the type of plot to generate can be entered. This card is the first to appear when the program begins execution. The latter is used for actually plotting the Mandelbrot or Julia set.

The MJSettings Card

This card is shown in Figure 2. It consists of six text fields, one image button, two text buttons, and one menu containing four menu items. Some of these items also have subitems associated with them. The card also has BeforeAttachment and AfterAttachment scripts as well as a local routine named DrawMJPic.

The BeforeAttachment Script for the MJSettings Card

This script executes just before the card is displayed. It checks to see if this is the first time the script has been executed (Invocation=0; all uninitialized variables default to a value of zero) and, if it is, sets default values for the maximum dwell, plot resolution, and plot type. These defaults can be changed via menu selections. The value of Invocation is set to one so these defaults will not be set again while the program is running.

The AfterAttachment Script for the MJSettings Card

This script first removes the check mark from all menu subitems and then adds a check mark to the appropriate subitems as determined by the current values of MaxDwell, Resolution, and PlotType. This is necessary since CanDo automatically puts check marks on the subitems with their Checked property set at design time. Next, the value of the first argument passed to the card, Arg1, is checked. If it is equal to "Reset", the six text fields are filled in with the current values of six variables. If this is not done, CanDo will automatically fill in the fields with the default values specified at design time. Finally, all of the text for the card (see Figure 2) is displayed.

The Text Fields

The six text fields are named LowReal, HighReal, LowImag, HighImag, JReal, and JImag. The first four fields (on the right side of the card) are for entering floating point numbers that define the rectangular plot region on the complex plane. The default values for these fields are -2.9, 2.9, -2.0, and 2.0, respectively. The JReal and JImag text fields (on the lower left corner of the card) are for entering floating point numbers that define the complex value, ci, that is used when plotting a Julia set. The default values are 0.5 and 0.0, respectively.

All six text fields have an OnRelease event script that simply activates the next field in sequence. This eliminates the need to activate each field by mouse clicking between entries. Be aware that the text fields will allow any alphanumeric character to be entered into the field. It would be nice if INOVAtronics would add a masked input field object to CanDo or, more preferably, provide a KeyPress event for field objects. The latter feature would allow a script to be executed each time the user presses a key while entering text into a field. This would allow programmer filtering of user input.

The Image and Text Buttons

The image button is named SeeMJPic and appears on the left side of the card. Clicking on the button causes the last generated plot to be displayed. The image for this button is a brush named CanDoMJButton.br. The OnRelease script for this button executes the routine DrawMJPic, passing the argument "SEE" to it.

The two text buttons are named GOC and GO. They appear in the lower right corner of the card. The former is used to generate a plot by calling a C program; the latter is used to generate the same plot using CanDo code. The OnRelease scripts for these buttons execute the DrawMJPic routine, passing arguments of "GOC" and "GO", respectively.

The DrawMJPic Routine

This routine extracts the text from each text field on the card and assigns their values to six appropriately named global variables. It then activates the MJPlotPic card, passing to it the argument that was passed to the routine itself. The content of the fields must be assigned to variables because the MJPlotPic card knows nothing of the fields on the MJSettings card but can access global variables.

The PlotInfo Menu

The MJSettings card has one menu structure named PlotInfo that contains four menu items. Some of the menu items have subitems. The menu structure looks like this:

	PlotInfo
		Max Dwell
			15
			31
			63
			127
		Resolution
			1
			2
			4
			8
		Plot Type
			Mandelbrot
			Julia
		Default Settings

Each selectable menu item or subitem has a shortcut key associated with it. They are shown in the definition sections of the menu objects in Listing 1.

The menu subitems under Max Dwell are mutually exclusive; only one item can be active at a time. A check mark appears next to the selected value. However, CanDo does not automatically handle mutually exclusive menu subitems. It will check the selected item, but it will not remove the check mark from any of the other items. This must be done by the programmer. As you can see from the Occurred scripts of the subitems (named MD15, MD31, MD63, and MD127), not only is the value of MaxDwell set, but the non-selected subitems have their check marks removed using the SetObjectState command. The same procedure is used by the subitems for Resolution and Plot Type. For the check marks to appear and disappear properly, be sure that the Checkmark property of the subitems are set at design time (see Figure 3).

The definition of maximum dwell has already been given and will not be discussed further. The meaning of plot type is obvious. So, let's discuss resolution.

The value of Resolution can be 1, 2, 4, or 8. When the value of Resolution is N, then an NxN pixel area will be drawn on screen for each calculated point in the Mandelbrot or Julia set. Thus, if Resolution is equal to 4, a 4x4 block of pixels will be colored for each calculated point. This allows rough but quick plots to be generated before actually plotting with a resolution of 1. Figure 4 shows a Julia set plot with a resolution of 4.

When the Default Settings menu item is selected, the text fields containing the plot range and ci value are set to their default values. This is accomplished by reactivating the MJSettings card without passing the "Reset" argument (see earlier discussion of the AfterAttachment script).

When creating a menu structure in CanDo, several levels of requesters must be filled in to create the menu items and subitems. These different requesters are shown together in Figure 3. Stepping through these requesters when creating a complex menu structure can be confusing. I would like to see these requesters combined into one well thought out requester.

The MJPlotPic Card

This card consists of a 320x200 32-color window with no system window objects. Thus, the card appears totally blank. However, the card does have one area button named NewRange and one menu structure named Options. The card also has an AfterAttachment script.

The AfterAttachment Script for the MJPlotPic Card

This script first checks the value of Arg1. If it is equal to "GO", a plot is generated with CanDo code. If it is equal to "GOC", a plot is generated using the C program, CanDoMJC. If it is equal to "SEE", the last generated plot is displayed.

If CanDo code is to be used to generate a plot, several variables are initialized, and either a Mandelbrot set or a Julia set plot is created depending on the value of PlotType. I leave it to you to follow through the code and see how it implements the formulas given at the beginning of this article. Several references are also given at the end of this article.

If the C program, CanDoMJC, is to be used to generate a plot, an AmigaDOS command line string is built up using several string concatenation operations and then executed using the Dos command. The final command will look something like this:

	RCF:C_Progs/CanDoMJC/CanDoMJC 3811064 31 2 -2.9 2.9 -2.0 2.0 J -0.5 0.0

The zeroeth parameter (as viewed by the C program) is the path and filename of the C program. The first parameter is the memory address of the Window data structure for the MJPlotPic card. This address is available through the CanDo system variable, WindowAddress. The second and third parameters are the values of MaxDwell and Resolution. The fourth through seventh parameters are the values representing the plot range. The eighth parameter is the plot type, M or J. Finally, the ninth and tenth parameters are the real and imaginary parts of the ci value used in Julia set plots. The C program is described below.

If the user just wants to view the last generated plot, then the file ram:CanDoMJPic, which is used to store the last plot (see below), is loaded into the MJPic buffer and displayed. Be aware that if no plot has yet been generated, the file ram:CanDoMJPic will not exist. In this case, CanDo will automatically display a file requester so the user can make a selection. Also, if you use TheMultiBinder to create a tool from this deck, do not include CanDoMJPic during the binding process. If you do, TheMultiBinder will add the current picture in this file to the bound deck. This prevents the program from loading the file each time it is to be displayed, thus always showing the same picture.

The NewRange Area Button

This button allows the user to click the left mouse button at any location on the screen, drag out a rectangle, and then release the button. By doing so, a new plotting range is set based on the rectangle boundaries. The button is 320x200 pixels in size and has no highlighting or border. Therefore, it covers the entire card and is invisible. The only reason for its existence is to detect mouse button clicks and movements. Neither the window object nor the card can handle mouse events. Thus, the entire card has to be covered with an invisible area button. The button has three scripts to allow it to function properly: OnClick, OnDrag, and OnRelease. OnClick executes when the left mouse button is pressed, OnDrag executes as the mouse is moved about while continuing to hold down the left mouse button, and OnRelease executes when the left mouse button is released.

The OnClick script determines the current location of the mouse from the system variables MouseX and MouseY. Also, the width and height of the rectangle are set to zero, the draw mode is set to COMPLEMENT, and an initial rectangle is drawn. As the mouse is moved, the OnDrag script executes over and over. It first draws another rectangle over top of the previously drawn rectangle. Since the draw mode is COMPLEMENT, this causes the previous rectangle to disappear. Next, the rectangle width and height are updated and another rectangle is drawn. This gives the appearance on screen that the rectangle is elastic and is stretching to match the mouse movements. This continues until the left mouse button is released. The OnRelease script first draws one final rectangle to erase the last one drawn. It then updates the real and imaginary plot ranges based on the boundaries of the rectangle. Next, the current picture is moved into buffer MJPic and saved to file ram:CanDoMJPic so that it can be recalled later if needed. Finally, card MJSettings is activated, passing an argument of "Reset" so the plot boundary fields will be updated. Be aware that the code only provides for the rectangle to be drawn from upper left to lower right. Trying to create the rectangle any other way will cause high and low values to be interchanged, thus producing upside down and backward plots.

The Options Menu

The MJPlotPic card has one menu structure named Options that contains three menu items. The menu structure looks like this:

	Options
		Save Picture
		Set Colors
		To Settings

Each menu item has a shortcut key associated with it. They are shown in the definition sections of the menu objects in Listing 1.

When Save Picture is selected, a file requester is displayed, allowing the user to select a filename to which to save the current plot. This is useful if you would like to move the picture into a paint or image processing software package for modifications.

When Set Colors is selected, the ChangePalette card in the ColorChange deck is opened as a requester, allowing the user to modify the colors of the plot (see Figure 5). The ColorChange deck was described in another one of my articles (AC 9.5).

When To Settings is selected, the current plot is saved to the temporary file ram:CanDoMJPic for later recall, and the MJSettings card is activated.

The CanDoMJC C Program

This program consists of two source files: a header file named CanDoMJC.h and the main file named CanDoMJC.c. The former is shown in Listing 2, the latter in Listing 3.

CanDoMJC.h, which is #included by CanDoMJC.c, #includes several system header files, #defines some macro variables, and declares some useful structures. It also contains two functions for opening and closing the intuition and graphics system libraries.

CanDoMJC.c contains two functions in addition to the mandatory main function. The first is named MJPlot. It is used to plot the requested Mandelbrot or Julia set. If you are familiar with C programming, you will see that the code is very similar to the CanDo plotting code in the AfterAttachment script for the MJPlotPic card. In fact, the algorithms are exactly the same and will produce identical plots for the same settings. The second additional function is named SetComplexRange and simply fills in a ComplexRange data structure with four floating point values passed as parameters to the function.

The main function declares several variables, calls the OpenLibraries function (see CanDoMJC.h), and then reads and converts all of the parameter strings passed to the program from the CanDo deck. The first parameter is the address of the Window data structure for the MJPlotPic card. The string is converted to an unsigned long integer which in turn is converted to a pointer to a Window data structure. With this address, the C program can draw directly on the MJPlotPic card. The remaining parameters are as described earlier and have their data types converted appropriately. Once the parameters are read (note that the last two parameters are only read if a Julia set plot is requested), the Mandelbrot or Julia set is plotted. Afterwards, the CloseLibraries function (see CanDoMJC.h) is called and the program ends.

The CanDoMJC program was compiled as shown in the listings with no errors or warnings using the SAS/C Development System Version 6.50. The compiler options were set such that the program uses the IEEE floating point libraries supplied with AmigaDOS. These are the same libraries used by CanDo for its floating point calculations. Thus the CanDo and C code are on equal footing when it comes to the actual floating point calculations. The difference in speed comes from the C code being compiled whereas the CanDo code is only semi-compiled. Also, CanDo spends time converting between data types whereas C uses variables with predetermined data types.

Speed Comparisons

As suspected, the C code generated plots quite a bit faster than did the CanDo code. The plot times discussed below apply to my Amiga 2000 with a 68030/68882 28MHz GVP accelerator card.

In general, the C code executed about 40-50 times faster than the CanDo code. For instance, the Mandelbrot set shown in Figure 1 (maximum dwell of 31) took 50 seconds to generate with the C code and 41 minutes to generate with CanDo code. The Julia set in Figure 6 (maximum dwell of 63) took 55 seconds in C and 38 minutes in CanDo. Thus, for floating point math intensive CanDo programs, it is advisable to write a C language support program to enhance the performance.

Other Front Ending Methods

CanDoMJ has a very simple link to its back end C program. It simply passes a window address along with some other numerical values to the C program. The C program does its thing and then exits. In other programs, there may need to be a two-way communication between the front end program and the C program. In this case, data could be transferred between programs via data files on the RAM: device. Or, if more sophisticated communications are needed, ARexx communications could be added to the C program. Of course, the authoring tool used for the front end would also need to support ARexx communications. CanDo does.

More Mandelbrot and Julia Set Information

If you have an interest in Mandelbrot or Julia sets, then you might want a subscription to AMYGDALA. This is a newsletter devoted to fractals, especially the Mandelbrot set, and is published by Rollo Silver, Box 219, San Cristobal, NM 85764. A 35mm slide supplement is also available.

There are many books on the market that discuss the Mandelbrot set, Julia sets, and fractals in general. Below is a list of several I own that you might find interesting.


Back to list of articles
Back to Randy Finch's Home Page
Last modified on April 1, 1996
Randy Finch at webmaster@rcfinch.com