home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1989
/
02
/
tracy.asc
< prev
next >
Wrap
Text File
|
1989-01-04
|
11KB
|
297 lines
_The Forth Column_
by Martin Tracy
[LISTING ONE]
\ 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