home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hot Shareware 32
/
hot34.iso
/
ficheros
/
DGRAF
/
FRAIN196.ZIP
/
IF_ELSE.TXT
< prev
next >
Wrap
Text File
|
1997-05-06
|
13KB
|
292 lines
FRACTINT'S NEW FLOW CONTROL INSTRUCTIONS FOR THE FORMULA PARSER
Version 19.6 of Fractint provides for flow control statements in user
created formulas. This feature should make formulas more readable, and
preliminary testing indicates that more complicated formulas will run as
much as 2 to 3 times faster when the formula is written using the new
instructions.
This tutorial provides an overview of the new feature. It assumes that
the reader is familiar with the syntax of Fractint formulas. If you are
new to Fractint, the documentation accompanying Fractint provides a good
start, and Bradley Beacham's tutorial (available in Library 3 of the
CompuServe Graphics Developers Forum as frmtut.zip, and at Noel Giffen's
Fractint web page - http://spanky.triumf.ca) will provide a more detailed
explanation of Fractint formula writing. Sylvie Gallet's tutorial on PHC
and PTC formulas is a more advanced text, and is available at the same
sites. These tutorials are also included in the Fractint v. 19.6 package.
Until Fractint v. 19.6, each section of a Fractint formula was always
executed one instruction at a time, sequentially through the section
without exception. Formula writers worked out ingenious solutions to
achieve different results in a formula based on a testing of some
condition. For example, if the writer wanted c to be equal to sin(z) if
x==y, and cos(z) if not, the formula would contain the following line:
c = sin(z)*(x==y) + cos(z)*(x!=y)
Each time this line is reached in the formula, which in the course of
drawing an image could be many millions of times, each element of the line
is computed, so both the x==y and the x!=y tests are evaluated (one of
which, of course, will be 0 and the other 1), and both sin(z) and cos(z)
are computed. Obviously, it would be much more efficient to evaluate only
x==y, and then compute only sin(z) or cos(z) depending on the result.
THE NEW FLOW CONTROL INSTRUCTIONS
Four new formula instructions are now permitted in a Fractint formula.
They are:
IF (expression)
ELSEIF (expression)
ELSE
ENDIF
Each of these instructions must be a separate statement in the formula,
i.e. must end with a comma or an end-of-line character.
The easiest way to avoid problems with this requirement is to put each
of these instructions on a separate line. The practice of the people
testing the new feature has been to capitalize the flow control
instructions and to indent the regular calculations which follow them.
A group of these instructions beginning with IF and ending with ENDIF
constitutes a unit which I'll refer to as an "if block" of instuctions.
A formula may contain any number of if blocks, and if blocks may be nested
inside other if blocks. The only limitation is that the end of the
initialization section (represented by a ":" in the formula) cannot be
inside an if block.
An if block contains exactly one IF, exactly one ENDIF, no more than 1
ELSE (there may be none), and any number of ELSEIFs (there may be none),
but all ELSEIFs must precede the block's ELSE instruction. The format is
therefore as follows:
IF (expression)
statements
ELSEIF (expression)
statements
ELSEIF (expression)
statements
.
.
ELSE
statements
ENDIF
ELSEIF (expression) is the equivalent of two flow control instructions,
an ELSE immediately followed by an IF (). The difference between the
single and the separated instructions is that ELSEIF does not require its
own ENDIF, whereas ELSE followed by IF would require that the separate IF
have its own ENDIF.
The example above, restated using these instructions, will read as
follows:
IF (x==y)
c = sin(z)
ELSE
c = cos(z)
ENDIF
Not only is this formulation intuitively easier to understand than the
earlier one, it also runs much faster, because only the elements necessary
to make the desired assignment to c are executed.
The formula parser does the following with these instructions:
1. Evaluate the expression inside the parentheses of the IF instruction.
Boolean expressions in Fractint (expressions which use the operators
==, !=, >, <, >=, <=, && and ||) alway evaluate to (1,0) if the
expression is true and (0,0) if the expression is false. The nature
of branching instructions is such that the expression in the
parentheses of an IF instruction will almost always be boolean, but
this is not a requirement. Any expression which evaluates to a
single complex number is acceptable. Thus, though unusual, the
instruction IF(x+y) is perfectly valid, since the result of x+y is a
complex number.
2. Look at the real element, and only the real element, of the
expression. If it is nonzero, the expression represents "true".
If the real element is zero, the expression represents "false".
Thus (1,0), (-1,0), and (3.14, 6) are all "true" results. (0,0),
(0,1) and (0,-1) are all "false" results.
3. If the expression is true, proceed to the next statement in the
formula without any skipping.
4. If the expression is false, skip to the statement immediately following
the next flow control instruction in the if block (of necessity, an
ELSE, the ELSE element of an ELSEIF(), or ENDIF), and begin further
processing from there.
5. If an ELSE or the ELSE portion of an ELSEIF() instruction is reached
in the course of processing, jump to the instruction following the
ENDIF at the end of that if block.
Looking at the above example, the parser first evaluates the expression
x==y. If it is true, the next statement, c = sin(x) is executed, and then,
the ELSE now being reached, execution jumps to the ENDIF. If x==y is
false, execution jumps straight to the statement after the ELSE, which is
c = cos(x), and executes it, continuing on from there.
With a little reflection you will realize that only one of the sets of
statements following flow control instructions in an if block is executed.
For example,
IF (expr1)
group1_statements
ELSEIF (expr2)
group2_statements
ELSEIF (expr3)
group3_statements
ELSE
group4_statements
ENDIF
If expr1 is true, the group1_statements will be executed and then the
execution will jump to the ENDIF. The fact that expr2 or expr3 may be
true is irrelevant; the conditions will not be tested if expr1 is true.
If expr1 is false, then expr2 will be tested, and if true the
group2_statements will be executed, and when done the execution will jump
to the ENDIF. expr3 is only evaluated if expr1 and expr2 are both false.
You can also see that the group4_statements will only be executed if all
three of the test expressions are false.
If there is no ELSE statement in an if block, it is possible that none of
the calculation statements in the block will be executed. For example,
IF (expression)
statements
ENDIF
will cause the statements to be executed only if the expression is true;
otherwise they are skipped entirely.
EXAMPLE
Carr2821 is one of Bob Carr's many formulas which make use of the
formula branching technique developed by Sylvie Gallet. It has received
much attention lately because of Lee Skinner's marvelous collection of 186
images derived from the formula.
Following is the original formula and an IF..ELSE rewrite of it. In
addition to the straightforward switch from the old method of branching to
the new, you will see that the flow control instructions make much easier
the implementation of other short cuts which speed up execution.
The IF..ELSE rewrite produces the same images as the original, but in
about 1/2 the time, depending on your processor.
Carr2821 {; Modified Sylvie Gallet frm. [101324,3444],1996
; passes=1 needs to be used with this PHC formula.
b5=pixel-conj(0.1/pixel)
b4=pixel-flip(0.1/pixel)-conj(0.001/pixel),
c=whitesq*b4-(whitesq==0)*b4
z=whitesq*b5-(whitesq==0)*b5
c1=1.5*z^1.2,c2=2.25*conj(z),c3=3.375*flip(z),c4=5.0625*flip(z),
l1=real(p1),l2=imag(p1),l3=real(p2),l4=imag(p2),
bailout=16,iter=0:
t1=(iter==l1),t2=(iter==l2),t3=(iter==l3),t4=(iter==l4),
t=1-(t1||t2||t3||t4),z=z*t,c=c*t+c1*t1+c2*t2+c3*t3+c4*t4,
z=(|z|/5)+z*z+c-0.09/pixel
iter=iter+1
|z|<=bailout
}
carr2821 {; Modified Sylvie Gallet frm. [101324,3444],1996
; Converted to if.else by Sylvie Gallet and George Martin 3/97
; passes=1 needs to be used with this PHC formula.
pixinv = 0.1/pixel
p9 = 0.9*pixinv
imagp1 = imag(p1)
imagp2 = imag(p2)
IF (whitesq)
z = zorig = pixel - conj(pixinv)
c = pixel - flip(pixinv) - conj(0.01*pixinv) - p9
mz = |z|
ELSE
z = zorig = conj(pixinv) - pixel
c = flip(pixinv) + conj(0.01*pixinv) - pixel - p9
mz = |z|
ENDIF
bailout = 16
iter = 0
:
IF (iter==p1)
z = mz = 0
c = 1.5*zorig^1.2 - p9
ELSEIF (iter==imagp1)
z = mz = 0
c = 2.25*conj(zorig) - p9
ELSEIF (iter==p2)
z = mz = 0
c = 3.375*flip(zorig) - p9
ELSEIF (iter==imagp2)
z = mz = 0
c = 5.0625*flip(zorig) - p9
ENDIF
z = mz*0.2 + z*z + c
mz = |z|
iter = iter + 1
mz <= bailout
}
REWRITING OLD FORMULAS
There are more than 1500 existing Fractint formulas which could be
written in IF..ELSE format. If you have occasion to rewrite one, you
should test the rewrite to make sure it is drawing the identical images
that the original version did. To perform this test, do the following:
1. Using a .par file image entry which uses the formula, render the image
using the old formula, and save the image (e.g. as oldimage.gif).
2. Using the same .par file image entry, render the image using the
rewritten formula, and save the image (e.g. as newimage.gif).
3. Exit Fractint, and restart with the following command line options
selected: debug=50 filename=oldimage.gif
4. With oldimage.gif on the screen, hit <r> and select newimage.gif to
restore to the screen. Hit <CR>
5. The effect of debug=50 is that the pixels which will be shown in the
second restored image will only be those which are different than the
image previously on the screen. If the images are identical, you will
have a completely blank screen.
6. Differences are saved to an ASCII file "cmperr". Exit Fractint and
check this file to assure yourself that the two images were in fact
identical.
Images drawn in floating point mode on a computer with a math coprocessor
or a 486 or higher processor may have slight pixel variation between an
original and an if..else rewrite because of certain optimizations
implemented in the "fast parser" code. If you are seeing these variations
and want to make sure the rewritten formula is accurate, draw the images
using the original and rewritten formulas with the command line parameter
debug=322 selected. This causes Fractint to skip the optimization code,
and differences caused by the optimizer will therefore be eliminated. If
you still have differences and believe your rewrite is accurate, try again
with debug=90 selected. This eliminates the use of the fast parser
entirely, and the original formula and your rewrite, if correct, should
produce identical images.
If you are satisfied that you have a good rewrite, post the revised
formula in a message in the Fractint forum on CompuServe, or send an email
with the revised formula to me (76440.1143@compuserve.com). It will be
helpful if the message includes both the old and rewritten formula, and a
.par image entry using the formula so that we can easily verify the
accuracy of the rewrite. Good rewrites will be added to the orgform
compilation of formulas in place of the old formula, with credit given to
the author of the rewrite.
Thanks to Sylvie Gallet and Les StClair for their help in writing this
tutorial.
George Martin
3/23/97