Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Database

The Forth Column


FEB89: THE FORTH COLUMN

The German Forth community has moved a step closer to claiming the domain of real-time programming. According to Klaus Schleisiek-Kern (DELTA-t), a German real-time congress with a strong Forth component is now being planned. Echtzeit '90 will take place in Nuremberg, the home of the first German Forth chip, in the summer of 1990. Sponsored by E-T-A GmbH, the chip was developed by Fraunhofer-Gesellschaft Erlangen, and will be produced by ELMOS GmbH. Klaus will talk about it at the 1988 FORML convention.

In other Forth news, Friends of Forth are invited to brush up on their syntax by participating in Jack Brown's ongoing Forth tutorial on the British Columbia Forth Board (604-434-5886). It is also being networked to GENIE (800-638-9636 sign-up) and the East Coast Forth Board (703-442-8695). The lessons, two of them so far, are well written and have excellent examples and homework problems. You can leave your solutions on the board for correction and feedback. The course is based on Tom Zimmer's public-domain F-PC Forth. The latest version, 2.15, is available on the same bulletin boards, although, it will take quite a while to download it. Or you might call Offete Enterprises (415-574-8250) to see if they already have it on a low-cost disk.

ANS X3J14 Meeting Number 5

The ANS Forth Technical Committee held its fifth meeting August 10 - 13 in Portland, Ore. For the first time, a BASIS document was presented that differs radically in format from the Forth-83 Standard. The content and wording of this document, nicknamed "Brave New Basis" (BNB), received quite a bit of attention at the meeting. Several new terms were defined, such as execution token, the token that ' ("tick") returns for EXECUTE to use. You can get a copy of the latest BASIS by sending $5 to Martin Tracy, FORTH Inc., 111 N. Sepulveda Blvd., Manhattan Beach, CA 90266.

The meeting dealt with over 70 technical proposals, more than double of the previous meeting. There was a feeling that the BASIS would become the draft proposal ANS Forth Standard (DPANS) sometime in 1989. This optimism abated somewhat when Charles Moore, the founder of the Forth language, left the meeting abruptly after one of his proposals was defeated. I have posted the draft minutes of the meeting and the current technical proposal. Log on GENIE as files TCMINS5.ARC and TECHPROS.ARC, respectively.

Here are some of the technical highlights of that meeting:

  • The " (quote) string literal compiler was added. The sequence "ccc" inside a colon definition will cause the address and length of the string ccc to be pushed on the stack, with the length on top.
  • 2@, 2!, 2DUP, 2DROP, 2SWAP, 2OVER, 2R>, and 2>R are now required words.
  • ASCII and [ASCII] have been added. ASCII used outside of a definition leaves the ASCII value of the first character of the following word on the stack.
  • [ASCII] has an equivalent action for use within a definition.
  • A floating-point extension was added. It includes the functions F+, F-, F*, F/, F0<, F0=, F<; the memory access words F@ and F!; the (separate) stack manipulators FDUP, FDROP, FSWAP, FOVER, and FROT; and the defining words FCONSTANT and FVARIABLE. At present, there is no proposal for floating-point input or output, nor is there any way to make a floating-point number.
  • The text file operators READ-LINE and WRITE-CR have been added to the file extension.

The next ANS X3J14 committee meeting is scheduled for the end of January 1989. It will be held in Los Angeles, Calif., and is hosted by Ray Duncan of Laboratory Microsystems. Observers are welcome. Call chair Elizabeth Rather at FORTH Inc. (213-372-8493) if you are planning to attend.

1988 ASYST International Conference

The first ASYST International Conference took place October 9 - 10 at the University of Rochester, N.Y. ASYST is one of the better known data acquisition and analysis packages and features a flexible graphics interface, disk data library support, and a rich library of mathematical functions, from statistics to signal processing. And best of all, it's programmable! ASYST is written in Forth, and much of the language is accessible at the user level.

To create a four-cycle, 256-point sine wave, for example, you would first make an array of 256 successive integers: 256 REAL RAMP

The elements generated by RAMP range from 1 to 256 and are located somewhere in a heap. A token representing this array is left on the stack. To adjust the integers to range from 0 to 255, subtract one: 1 -

The subtraction operator knows to subtract the scalar one from each element in the array. A token pointing to the resulting array is left on the stack. The index array is then normalized to range from 0 to a little less than 2 PI:

  256 / 2 * PI *

Finally, take four times the sine of each element:

  RAD 4 * SIN

To duplicate the array and plot is a simple matter:

  DUP Y.AUTO.PLOT

Of course, this could all be compiled into a colon definition:

  :FOURSINE ( - array)
        256 REAL RAMP 1 - 256 /
        2 * PI * 4 * SIN
        DUP Y.AUTO.PLOT;

ASYST supports the GPIB bus and more than two dozen IBM PC data acquisition and control drop-in boards. I was impressed by their (copyrighted) DAS driver specification, which describes a logical data acquisition and control board --timers, triggers, multi-channel A/D, DMA, the whole nine yards. This specification is not included in the ASYST package but comes with the notice that "ASYST authorizes any person or entity in possession of this specification to reproduce and distribute copies of this specification free of charge, provided that such copies are complete and entire and contain all copyright notices indicating ASYST's ownership of the copyright as are contained in the original." Call them at 716-272-0070.

The conference was smoothly executed by veteran Larry Forsely, who also puts together the Rochester Forth Conference. Here are some of the papers you missed:

"A General Purpose Stimulus Presentation and Data Acquisition System for the Cognitive Psychology/Evoked Potential Laboratory," by Dr. George Fein, UC San Francisco.

"Femtosecond Spectroscopy with ASYST," by Wayne Know, AT&T Bell Labs.

"Cables and Bits (the assessment of lung dysfunction)," by Dr. Daniel Rayburn, Walter Reed Institute of Research.

There were more than 40 papers in all, an impressive technical program for a first conference. I will let you know when the proceedings are available.

A Simple Mandelbrot

Hats off this month to Marc Hawley for his elegantly simple Mandlebrot program. The plotting routines, in their entirety, can be found on screen 2 (see Listing One , page 149). They use DOS calls to plot pixels on an IBM high-resolution (black and white) graphics screen, but you could alter them for fancier pictures. The routine itself is on screen 3. Several different views are developed by simply copying the screen and editing the parameters. The familiar inkblot appears from one to ten minutes after execution. The MANDLZEN.ARC file itself was downloaded from the GENIE FORTH bulletin board.

[<LISTING .+>\]/,"[$1]")

[LISTING ONE]

<a name="007c_0009"><a name="007c_0009">


\   MANDLZEN    9-16-88                               M.HAWLEY
\
   This file contains a screen for graphics words for an IBM-PC
BIOS compatible. The word GRAPH puts the computer in high res.
graphics mode. PIXEL-ON takes two numbers off the stack and uses
them as X,Y coordinates to plot one pixel. PIXEL-OFF does the
same but turns the pixel off. All other words are FORTH-83
written in L&P F83.
   The load screen loads screen 2 , the graphics words
and screen 3 which draws a small sketch of the Mandelbrot Set
in under 8 minutes.
   The other screens draw bigger versions and closeups. Full
blown versions take up to 4 hours to draw on my 8086 based PC.
LOAD THE SCREEN YOU WANT TO RUN. You can't load them all at once
because they all use the same variables and constants.

\                                                     M.HAWLEY
2 3 THRU


\                                                     M.HAWLEY
HEX
 CODE VIDEO     AX POP DX POP CX POP
 BP PUSH  SI PUSH  10 INT SI POP BP POP
 NEXT  END-CODE
: TEXT  0 0 2 VIDEO  ;
: GRAPH 0 0 6 VIDEO  ;
CODE PLOT    AL POP   DX POP  CX POP
0C # AH MOV
 BP PUSH  SI PUSH  10 INT SI POP  BP POP
 NEXT END-CODE
CODE PIXEL-ON  0C01 # AX MOV   DX POP CX POP
   BP PUSH SI PUSH 10 INT SI POP BP POP NEXT END-CODE
CODE PIXEL-OFF 0C00 # AX MOV  DX POP CX POP
   BP PUSH SI PUSH 10 INT SI POP BP POP NEXT END-CODE
DECIMAL ;
\   MANDLZEN  One screen Mandlbrot sketch             M.HAWLEY

      VARIABLE CX  VARIABLE CY  VARIABLE X
-8192 CONSTANT CYBASE  CYBASE CY !  -12000 CX !
  160 CONSTANT CXSTEP   400 CONSTANT CYSTEP
 : MANDLZEN GRAPH  269 X !    370 270 DO  1 X +!
    125 75 DO  0 0   X @ I PIXEL-ON
 30 0 DO     2DUP DUP 8192 */  SWAP DUP 8192 */
   2DUP + 0< IF X @ J PIXEL-OFF 2DROP  LEAVE THEN
     SWAP - CX @ + -ROT 4096 */ CY @ + LOOP 2DROP
    CYSTEP CY +!
 LOOP  CYBASE CY !
      CXSTEP CX +!  LOOP ." Mandelbrot by Marc Hawley "
." POB 716, Mt. Vernon, IN 47620 "    ;


\  MANDL1    Full screen Mandelbrot portrait          M.HAWLEY

      VARIABLE CX  VARIABLE CY  VARIABLE X
-8192 CONSTANT CYBASE  CYBASE CY !  -12000 CX !
  33 CONSTANT CXSTEP   82 CONSTANT CYSTEP
 : MANDL1 GRAPH  0 X !    500 0 DO  1 X +!
    200 0 DO  0 0   X @ I PIXEL-ON
 50 0 DO     2DUP DUP 8192 */  SWAP DUP 8192 */
   2DUP + 0< IF X @ J PIXEL-OFF 2DROP  LEAVE THEN
     SWAP - CX @ + -ROT 4096 */ CY @ + LOOP 2DROP
    CYSTEP CY +!
 LOOP  CYBASE CY !
      CXSTEP CX +!  LOOP ." Mandelbrot by Marc Hawley "
." POB 716, Mt. Vernon, IN 47620 "    ;


\  MANDL1    full screen                              M.HAWLEY

-200 CONSTANT CYBASE  CYBASE CY !  2000 CX !
  1 CONSTANT CXSTEP   2 CONSTANT CYSTEP   0 X !
 : MANDL1 GRAPH      500 0 DO  1 X +!
    200 0 DO  0 0   X @ I PIXEL-ON
 80 0 DO     2DUP DUP 8192 */  SWAP DUP 8192 */
   2DUP + 0< IF X @ J PIXEL-OFF 2DROP  LEAVE THEN
     SWAP - CX @ + -ROT 4096 */ CY @ + LOOP 2DROP
    CYSTEP CY +!
 LOOP  CYBASE CY !
      CXSTEP CX +!  LOOP ;




\  MANDL3    full screen                              M.HAWLEY

-8192 CONSTANT CYBASE  CYBASE CY !  -1024 CX !
  2 CONSTANT CXSTEP   5 CONSTANT CYSTEP   0 X !
 : MANDL3 GRAPH      500 0 DO  1 X +!
    200 0 DO  0 0   X @ I PIXEL-ON
 80 0 DO     2DUP DUP 8192 */  SWAP DUP 8192 */
   2DUP + 0< IF X @ J PIXEL-OFF 2DROP  LEAVE THEN
     SWAP - CX @ + -ROT 4096 */ CY @ + LOOP 2DROP
    CYSTEP CY +!
 LOOP  CYBASE CY !
      CXSTEP CX +!  LOOP ;




\  MANDL4    full screen                              M.HAWLEY

-8192 CONSTANT CYBASE  CYBASE CY !  -1024 CX !
  2 CONSTANT CXSTEP   5 CONSTANT CYSTEP   0 X !
 : MANDL4 GRAPH      500 0 DO  1 X +!
    200 0 DO  0 0   X @ I PIXEL-ON
 30 0 DO     2DUP DUP 8192 */  SWAP DUP 8192 */
   2DUP + 0< IF X @ J PIXEL-OFF 2DROP  LEAVE THEN
     SWAP - CX @ + -ROT 4096 */ CY @ + LOOP 2DROP
    CYSTEP CY +!
 LOOP  CYBASE CY !
      CXSTEP CX +!  LOOP ;




\  MANDL5    full screen                              M.HAWLEY

-8192 CONSTANT CYBASE  CYBASE CY !  -824 CX !
  1 CONSTANT CXSTEP   2 CONSTANT CYSTEP   0 X !
 : MANDL5 GRAPH      500 0 DO  1 X +!
    200 0 DO  0 0   X @ I PIXEL-ON
 90 0 DO     2DUP DUP 8192 */  SWAP DUP 8192 */
   2DUP + 0< IF X @ J PIXEL-OFF 2DROP  LEAVE THEN
     SWAP - CX @ + -ROT 4096 */ CY @ + LOOP 2DROP
    CYSTEP CY +!
 LOOP  CYBASE CY !
      CXSTEP CX +!  LOOP ;




\  MANDL6    full screen                              M.HAWLEY

-7250 CONSTANT CYBASE  CYBASE CY !  -424 CX !
  1 CONSTANT CXSTEP   2 CONSTANT CYSTEP   0 X !
 : MANDL6 GRAPH      500 0 DO  1 X +!
    200 0 DO  0 0   X @ I PIXEL-ON
 20 0 DO     2DUP DUP 8192 */  SWAP DUP 8192 */
   2DUP + 0< IF X @ J PIXEL-OFF 2DROP  LEAVE THEN
     SWAP - CX @ + -ROT 4096 */ CY @ + LOOP 2DROP
    CYSTEP CY +!
 LOOP  CYBASE CY !
      CXSTEP CX +!  LOOP ;




\ MANDELZEN DOCUMENTATION    9-16-88                  M.HAWLEY
VARIABLES   CX and CY are the X and Y coordinates of the
starting point for the graph. Everything is scaled up by a
factor of 8192, so -1 is expressed as -8192, .02 is expressed
as 164 and so on. The variable X is a kludge I had to use to
access the outermost index of three nested loops while in the
innermost. My version of L&P F83 has I and J for the first
two indexes but no I' ( drat ).
    To explore different parts of the Mandelbrot Set, change
the starting point by editing CX and CY.
CONSTANTS   CYBASE is the base value for CY. After the program
scans through the range of values being tested along the Y-axis
CY is reset to CYBASE for the next vertical scan.
    CXSTEP and CYSTEP are the increments by which CX and CY
are changed each time. To explore a large part of the Set or
all of it, use large STEPs.
\  DOCs cont.                                         M.HAWLEY
To zoom in and magnify a small part of the Set, use small
STEPs. For the best proportion, at least on my screen, CYSTEP
should be 2 or 2 1/2 times as big as CXSTEP.

PIXEL-ON and PIXEL-OFF are specific to IBM-PC BIOS ROM
compatibles. Given two numbers on the stack, they turn on
or off the pixel at that (X,Y) location on the screen.

You will notice that the closeup screens magnify the view
of screen 3 ( MANDLZEN ) up to 160 diameters just like a
160 power telescope looking at a celestial object. Yet, the
program is entirely in 16 bit scaled integer math ---
no floating point. I originally thought that THIS program
would HAVE to be in floating point.

\ DOCs                                                M.HAWLEY
    I first wrote it in floating point. It ran 6 TIMES SLOWER
than present version. For my fellow intermediate programmers
take notice. I now finally begin to understand why FORTH
programmers scoff at floating point.

THE ALGORITHM     Two numbers are kept on the stack representing
the real and imaginary components of a complex number. This
number is repeatedly put through the transformation:
         Z --> Z*Z + C
The complex number is sqared and added to another complex
number, C , which is the point being tested to determine whether
it is in the Set. C is represented as CX , the real part, and
CY the imaginary part. The sum is again squared and added to C.
This is repeated untill the test is satisfied ( Z stays small )
or failed ( Z gets too big ).
\  DOCs                                               M.HAWLEY
   The outer loops simply scan through the x and y coordinates
of the screen or some part of the screen and update the
variables.
   The inner loop is the repetative test which finds Z*Z + C.
The odd thing about squaring an imaginary number is that the
result is always negative. ( A positive OR negative real number
squared is always positive, of course. ) So what we need on the
stack for the real part of Z*Z + C is ZR*ZR-ZI*ZI + CX
and for the imaginary part 2*ZR*ZI + CY.
    Why ? Well :
 Z*Z = (ZR + ZI)*(ZR + ZI)
     = ZR*ZR + 2*ZR*ZI + ZI*ZI  but ZI*ZI is negative so...
     = ZR*ZR + 2*ZR*ZI - ZI*ZI
 The real part is ZR*ZR - ZI*ZI , imaginary 2*ZR*ZI
 Add the C :  ZR*ZR-ZI*ZI+CX    ,           2*ZR*ZI+CY    qed.
\ DOCs                                                M.HAWLEY
The inner loop first puts 0 0 on the stack for starters.
    WORD      :     STACK
             -->    0  0
  X  @ I     -->    0  0  X I
 PIXEL-ON    -->    0  0  plot the point being checked
             -->   ZR  ZI the values being represented
 2DUP        -->   ZR  ZI  ZR  ZI
  DUP        -->   ZR  ZI  ZR  ZI  ZI
8192 */      -->   ZR  ZI  ZR  ZI*ZI  scaled down by 8192
 SWAP        -->   ZR  ZI  ZI*ZI  ZR
 DUP         -->   ZR  ZI  ZI*ZI  ZR  ZR
8192 */      -->   ZR  ZI  ZI*ZI  ZR*ZR   scaled
 2DUP        -->   ZR  ZI  ZI*ZI  ZR*ZR  ZI*ZI  ZR*ZR
 +           -->   ZR  ZI  ZI*ZI  ZR*ZR  ZI*ZI+ZR*ZR
         this is the square of the magnitude
\    DOCs                                             M.HAWLEY
The magnitude of a complex number is its distance from the
origin, the 0,0 point. The X and Y coordinates are two sides
of a triangle and the hypotenuse is the magnitude. Using the
Pythagorean Theorem, Mag*Mag = ZR*ZR + ZI*ZI
If the magnitude of Z is over 2 the point will continue to
grow and is not in the Set. But the square of the magnitude
is easier to find, so check if it is over 4. Here is a trick.
If you scale up by a factor of 1000 you will be checking for
a magnitude of 4000. Fine. For more detail you might try a
scale of 2000 and test for 8000. Still fine. Try a scale of
8000. Trouble. We are then testing whether a number is greater
than 32000, but if it is over 32768 it will show up as a
NEGATIVE number and pass the test it should fail. SO AHA !
Use a scale of 8192 and test for 32768 which is similar to
testing for a negative number. Mag. should not be negative.
\ DOCs                                                M.HAWLEY
             -->  ZR ZI  ZI*ZI ZR*ZR ZI*ZI+ZR*ZR
             -->  ZR ZI  ZI*ZI ZR*ZR magnitude.squared
    0<       -->  ZR ZI  ZI*ZI ZR*ZR  TF less than zero ?
    IF       -->  ZR ZI  ZI*ZI ZR*ZR
X @ J PIXEL-OFF      if test failed, erase pixel
 2DROP               if failed, drop two numbers
LEAVE THEN        ZR ZI failed, exit test
             --> ZR ZI  ZI*ZI ZR*ZR  if test passed
 SWAP        --> ZR ZI  ZR*ZR ZI*ZI
  -          --> ZR ZI  ZR*ZR-ZI*ZI  real part of Z*Z
 CX @        --> ZR ZI  ZR*ZR-ZI*ZI CX real part of C
  +          --> ZR ZI  ZRnew
 -ROT        --> ZRnew  ZR ZI
4096 */      --> ZRnew  2*ZR*ZI scaled ( 2/8192 = 1/4096)

\  DOCs                                               M.HAWLEY
               --> ZRnew  2*ZR*ZI
  CY @         --> ZRnew  2*ZR*ZI  CY   imag. part of C
  +            --> ZRnew  2*ZR*ZI+CY    this is new ZI
               --> ZRnew  ZInew
  LOOP         -->  test again ...
 2DROP         -->  clear stack when done
CTSTEP CY +!   -->  increment CY , the Y axis variable
 LOOP          -->  cycle through the Y axis
CYBASE CY !    -->  reset CY for the next CX cycle
CXSTEP CX +!   -->  increment CX, the X axis variable
 LOOP          -->  cycle through the X axis
  ;            -->    That's all, folks !
I would like to hear your comments and improvements.
Marc Hawley POB 716, Mt. Vernon, IN 47620
   EXPLORE AND ENJOY THE MANDELBROT SET











Copyright © 1989, Dr. Dobb's Journal


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.