Formula Compiler tutorial |
Introduction to the Fractal Explorer Formula Compiler version 2.03.02 September 2004 Written by Sirotinsky Arthur, Olga Fedorenko http://www.eclectasy.com/Fractal-Explorer/index.html sarthur71@mail.ru and Denis McCauley http://ata-tenui.ifrance.com/ |
0 Changes 1 Acknowledgements 2 Limitations 3 Introduction 3.1 What is the formula compiler ? 3.2 Formula Files 4 Formula anatomy 4.1 Formula is a programme 4.2 Formula is a Delphi/Pascal programme 4.3 Requirements 4.4 Simple project example 4.5 Temporary variables declaration 4.6 Advanced project example 4.7 The complex functions 4.8 Bailout test 5 Complex variables functions 5.1 List of the functions and procedures 5.2 Functions selector 6 Examples of the new formula sintax 7 List of changes
Version 2.03 has no fundamental differences from version 2.02. The basic achievement of this version is a significant speed improvement. Also, little bug fixed and added the two new functions: CConj and CConjV. Besides the constant CPixel was added. This constant contains the source complex value of the pixel which is currently calculated (i.e. Z0). The version 2.03 is a further development of the compiler and contains many new complex-variable functions. There are now 30 such functions. But the main innovation is that in the formulae two selectors of functions can be used, operate with which it is possible from the "Select fractal" window. So, now the formulae can be changed without compilation. In the following version we shall try to optimise libraries and to increase speed of calculations. Version 2.01 of the formula compiler has few but very important changes. First of all, now you do not need to write the difficult expressions for formula realization. We have added support for many operations and functions of complex values. Also, we added four complex variables for using in your functions. In part number [5] we describe these new possibilities. Please, read it before using the formula compiler.
Bradley Beacham for FRMTUTOR.TXT AN INTRODUCTION TO THE FRACTINT FORMULA PARSER Borland /Inprise/ Corp. for Delphi Command Line compiler
Our formula compiler is not a parser. It's a part of the program, which calculates one step of the iteration process. It can't read formula directly, since the complex type is non-standart type for Delphi.
3.1 What is the formula compiler ?It is a new part of the fractal-generating programme, Fractal Explorer (version 1.13 and greater). FE has many different types of the fractal formulae itself, the formula compiler allows you to add new fractals without having to change the programme. These formulae are stored in fractal spot files, and may be viewed and edited by anuther user. 3.2 Formula FilesNew formulae will be not saved to another file. Formula will be stored as fractal spot file (*.frs), which contain internal data for generating of the image. Therefore, FE requires one FRS file for building one image (and the formula is already implemented into the file).
4.0 Why a compiler ?Compiled programmes always work more quickly than interpreter. However, don't be surprised that the formulae written by you work too slowly. Please remember that the formulae that are built into the programme are specially optimised for calculation speed. Unfortunately, such optimisation is impossible for the formulae connected from the outside. We continue to work with this problem and we hope to solve it in the future. So, you can see, what each new version works quickly then previous. :o) 4.1 Formula it's a programFractal Explorer uses a formula's text for building Dinamic Link Libraries (DLL), and after that loads the new DLL (for interest - look to the system TEMP folder: strings "SET TMP=" or "SET TEMP=" in your c:\autoexec.bat). When the formula changed (or FE closed) the DLL will be unloaded from memory and deleted with the project source. 4.2 Formula it's a Delphi/Pascal programTo compile a new formula, FE will create the Delphi project file (*.DPR) in the temporary folder and execute Borland Delphitm Command Line compiler to generate the DLL file. Since we are using Delphi for writing Fractal Explorer, we are using Delphi for DLL compilation. 4.3 RequirementsTo use the Formula Compiler in FE the files listed below are required: All files must exist in the Fractal Explorer folder. FE will be check for
the presence of these files before compiling the new formula. If you have
lost one or more files - download full archive from: 4.4 Simple project exampleComplex numbers are two-part numbers: the first part is thr real part, and thr second part is the imaginary part. The notation of complex numbers is: Z = X + jY
where "j" - imaginary part attribute (square root from "-1"). Fractal Explorer uses this format for complex numbers. To illustrate a fractal formula take the Mandelbroth Set: z_new = z * z + c
You write in the edit box:
var k: Extended; Begin k:=(x+y) * (x-y) + cr; y:=2 * x * y + ci; x:=k; End; "x" is the real part of "z" complex number, and "y" the imaginary part. "cr" is the real part of "c" complex number, and "ci" the imaginary part. "z" is the value received in the "x" and "y" variables. New value of "z" will be returned in these variables. The variable "k" is used to store the new "x" values before calculating new "y" values. Press the "Compile" button and FE will make a Delphi project for this formula: library proba; Uses ShareMem, SysUtils, Math; Procedure Formula( var x, y, cr, ci: Extended; const p1r, p1i, p2r, p2i, p3r, p3i, p4r, p4i: Extended; var cA1, cA2, cA3, cA4: TComplex; const CPixel: TComplex; const Fn1, Fn2: Integer); export; var k: Extended; Begin k:=(x+y) * (x-y) + cr; y:=2 * x * y + ci; x:=k; End; exports Formula index 1 name 'Formula'; BEGIN END. For Delphi and Pascal programmers this code are simple. Other peoples may be interested only in Procedure Formula declaration: Procedure Formula( var x, y, cr, ci: Extended; const p1r, p1i, p2r, p2i, p3r, p3i, p4r, p4i: Extended; var cA1, cA2, cA3, cA4: TComplex; const CPixel: TComplex; const Fn1, Fn2: Integer); export; Variables:
You can modify values of cr and ci variales in your formulae. There are lot of the good formulas used this feature. For example: var c1,c2: Extended; Begin c1:=x; c2:=y; k:=(x+y) * (x-y) + cr; y:=2 * x * y + ci; x:=k; cr:=c1; ci:=c2; End; Values, received in p1r, p1i, .. , p4r, p4i parameters are real and imaginary parts of the P1, P2, P3 and P4 parameters of the fractal (look to the "Select formula" window). They are constant for your formula. You can't modify values of these variables. But you can use cA1,..cA4 variables to send the data from one iteration to another. This variabels available for modifing and they are initialized to zero before each pixel calculation. That's all, folks ! NOTE: do not write calculation cycle; Fractal Explorer does it itself!!! 4.5 Temporarly variable declarationSeparate your formula into small parts and use temporary variables (remember, that it requires the "var" section). Sintax for a temporary variable declaration: var name1, name2, name3: [type]
Type may be "Single", "Double", "Extended" or "TComplex". Comparsion of those types:
The «Double» type is used by default and we recommend it to you. The special type for the complex numbers is declared in the Formula Compiler: TComplex = record real: Extended; imag: Extended; end; You can declare variables of this type in your formulae to store complex numbers and use internal functions and procedures. By the way, variables cA1, cA2, cA3 and cA4 has TComplex type too. Examles:var tmp1,tmp2: Double; Begin <>formula...<> End; 4.6 Advanced project exampleMandel/Talis formula:
z_new = z*z + c;
c_new = c*c/(c+P1) + z_new; Write in the edit area: var h1x,h1y, h2x,h2y, f: Extended; // -temporary variables Begin h1x:=(x+y)*(x-y)+cr; // -calculating z_new y := x*y*2 +ci; // z_new = z*z + c x := h1x; h1x:= (cr+ci)*(cr-ci); // -h1 = c*c h1y:= cr*ci * 2; h2x:= cr+p1r; // -h2 = c+P1 h2y:= ci+p1i; f := h2x*h2x+h2y*h2y+1E-10; // -c_new=h1/h2 + z_new cr :=(h2x*h1x+h2y*h1y)/f+x; ci :=(h2x*h1y-h2y*h1x)/f+y; End; Calculate new values for "x" (real part) and "y" (imaginary part) of complex variable "z". Also, change cr and ci values - real and imaginary parts of "c". Next step will use z_new and c_new. 4.7 The complex functionsYou can use any function of the complex variables in your formula, but you must describe them, like this (remember, that Z = X + jY and C = CR + jCI): z*z: X_new := (X-Y)*(X+Y); Y_new := 2 * X*Y; z*c: X_new := X*CR - Y*CI; Y_new := X*CI + Y*CR; z*z*z: X_new := X*(X*X-3*Y*Y); // -this is optimized formula Y_new := Y*(3*X*X-Y*Y); z*z*z*z: tmp_r := (X-Y)*(X+Y); tmp_i := 2 * X*Y; X_new := (tmp_r - tmp_i) * (tmp_r + tmp_i); Y_new := 2 * tmp_r * tmp_i; 1/z: tmp := X*X + Y*Y + 1E-25; // -without 1E-25 may by X_new := X / tmp; // divizion by zero Y_new :=-Y / tmp; 1/(z*z): tmp := X*X + Y*Y; tmp := tmp * tmp + 1E-25; // -see above X_new := (X*X - Y*Y) / tmp; Y_new := (2*X * Y ) / tmp; Sqrt(z): tmp := Sqrt(X*X + Y*Y); X_new := Sqrt(Abs((X + tmp)/2)); Y_new := Sqrt(Abs((tmp - X)/2)); Exp(z): tmp := Exp(X); // e^z X_new := tmp * Cos(Y); Y_new := tmp * Sin(Y); Exp(1/z): tmp := X*X + Y*Y + 1E-25; // -see above s1 := X/tmp; s2 :=-Y/tmp; tmp := Exp(s1); X_new := tmp * Cos(s2); Y_new := tmp * Sin(s2); Ln(z): X_new :=Log2(X*X+Y*Y)/2.7182818285; Y_new :=ArcTan2(Y,X); z^c: h1x :=Log2(X*X+Y*Y)/2.7182818285; // -Ln(z) h1y :=ArcTan2(Y,X); h2x :=h1x*CR - h1y*CI; // -Ln(z)*c h2y :=h1y*CR + h1x*CI; f :=Exp(h2x); // -Exp(Ln(z)*c) X_new :=f*Cos(h2y); Y_new :=f*Sin(h2y); Sin(z): tmp := Exp(Y)/2; // -optimized formula (!) tmp2 := 0.25/tmp; X_new := Sin(X) * (tmp+tmp2); Y_new := Cos(X) * (tmp-tmp2); Cos(z): X_new := Cos(X)*Cosh(Y); // -not optimized formula Y_new :=-Sin(X)*Sinh(Y); Tan(z): X_new := Sin(2*X)/(Cos(2*X)+Cosh(2*Y)); Y_new := Sin(2*Y)/(Cos(2*X)+Cosh(2*Y)); Sinh(z): // -hiperbolic sinus X_new := Sinh(X)*Cos(Y); // -it is not optimized formula Y_new := Cosh(X)*Sin(Y); Cosh(z): // -hiperbolic cosinus X_new := Cosh(X)*Cos(Y); // -it is not optimized formula Y_new := Sinh(X)*Sin(Y); You must change X, Y, CR and CI variables to those, which required by you formula. 4.8 Bailout testA new feature has been included in the Formula Compiler in Fractal Explorer 1.24 beta 1. In addition to the two main bailout tests (M-set and N-set) you can add your custom tests to the bailout function. What is a difference between M-Set and N-Set? The M-Set bailout test performs an exit from the loop when the modulus squared of the complex number exceeds the specified value. For example, |Z|>4 performs the loop again and again while |Z| is less 4. Once |Z| exceeds 4 the calculation loop will stop. This is a classical Mandelbrot-like bailout test; fractals based on this algorithm are sometimes called "Escape-Time To Infinity" fractals. The N-Set bailout test is a fundamentally different test. This test checks the difference between the current iteration and the precedent iteration. A classical example of the N-Set test is: |Z-Zold|<0.0001. Such fractals are sometimes called "Escape-Time To Finity" fractals, and the N-Set bailout test is sometimes called "F-Set" (finity-set). The N-set calculation loop will finish when the modulus squared of the difference between the current value and the previous value is less than 0.0001. To perform the N-Set test we should pass the value of Z from the current cycle to the next. The common algoritm of the N-Set is listed below:
var OldZ: TComplex Begin <..> If iter_number=1 Then OldZ:=MakeComplex(0,0); Z:=Z-(Z^2+1)/(2*Z); If |Z-OldZ|<0.0001 Then EndLoop:=True; OldZ:=Z; End; In the init section the OldZ variable is set to zero. The next strings are calculation of the loop. First - calculate the new value of Z; second - perform the N-Set bailout test and set the "EndLoop" variable to "True" if the test is passed. The last string of the code saves the current Z value to the OldZ variable and sends this value to the next cycle. Formula Compiler implementation:To perform the user-defined bailout tests you may use global variable var EndLoop: Boolean; .
Before the loop this variable is set to FALSE. If the bailout test is passed - you may set EndLoop to TRUE: EndLoop:=True;
Remember that if the answer of a bailout test is "FALSE", the loop must be performed again; otherwise, it is time to quit iterating. In addition, a new function to calculate the squared modulus of the complex number has been added: CModule(complex: TComplex);
Let us check an example to learn more about user-defined bailout tests: var Z,C,P1 : TComplex; T1,T2,T3 : TComplex; Begin Z :=MakeComplex(x,y); C :=MakeComplex(cr,ci); P1:=MakeComplex(p1r,p1i); // CGNewtonSinExp by Chris Green // z1=exp(z), // z2=sin(z)+z1-z, // z=z-p1*z2/(cos(z)+z1), T1:=CExp(Z); T2:=CSub(CAdd(CSin(Z),T1),Z); T3:=CAdd(CCos(Z),T1); Z :=CSub(Z,CDiv(CMul(P1,T2),T3)); SetResult(x,y, Z); // bailout test: .000001 < |z2| If CModule(T2)<0.000001 Then EndLoop:=True; End;
5.1 List of the functions and proceduresThe special type for storing of the complex numbers was described above. You need to remember this declaration: Type TComplex = record real: Extended; imag: Extended; end; All of the functions listed below will use this type for their operations. It's a very important part of the new version Formula Compiler. List of the functions and proceduresI. Function MakeComplex(real, imag: Extended): TComplex; This function makes a TComplex value from the two values, which describe the real and imaginary parts of the complex value. Use this function for translate the input values (x,y, cr,ci and p1r..p4i) to the complex type. After translation you can use result in another functions and procedures. Also, you can use this function to make a TComplex value from a constant, for example: tmp:=MakeComplex(3,0) - convert the real number "3" into TComplex type. II. Procedure SetResult(var x,y: Extended; const complex: TComplex); This procedure makes final results accessible for the Formula Compiler. As described in the part [4.4], the result values must be returned in the "X" and "Y" variables. You can use two operations for it: x:=Z.real; y:=Z.imag; but now you can use the SetResult procedure for this. Note: remember, what the SetResult procedure works little bit slowly then direct storing the data. Below are listed functions and procedures for mathematical operations. Every operation has two releases: first, as a procedure with no result returned, and second, as a function, which returns the result of the operation as a TComplex value. Any procedure keeps the resulting complex value in the variable which passed as the first parameter. III. Sum of the two complex: Procedure CAddV(var Cmp1: TComplex; const Cmp2: TComplex); Cmp1 := Cmp1 + Cmp2; Result value will be returned in the "Cmp1" variable. Function CAdd (const Cmp1, Cmp2: TComplex): TComplex; Cmp3 := Cmp1 + Cmp2; Result value will be returned as a result of the function. Function CAddR (const Cmp1: TComplex; t: Extended): TComplex; Cmp2 := Cmp1 + t Added real value "t" to the "Cmp1" complex. IV. Subtraction of the two complex: Procedure CSubV(var Cmp1: TComplex; const Cmp2: TComplex); Cmp1 := Cmp1 - Cmp2; Function CSub (const Cmp1, Cmp2: TComplex): TComplex; Cmp3 := Cmp1 - Cmp2; Function CSubR (const Cmp1: TComplex; t: Extended): TComplex; Cmp2 := Cmp1 - t; V. Multiplication of the two complex: Procedure CMulV(var Cmp1: TComplex; const Cmp2: TComplex); Cmp1 := Cmp1 * Cmp2; Function CMul (const Cmp1, Cmp2: TComplex): TComplex; Cmp3 := Cmp1 * Cmp2; Function CMulR (const Cmp1: TComplex; t: Extended): TComplex; Cmp2 := Cmp1 * t; (Cmp2.real = Cmp1.real*t Cmp2.imag = Cmp1.real*t) VI. Division of the two complex: Procedure CDivV(var Cmp1: TComplex; const Cmp2: TComplex); Cmp1 := Cmp1 / Cmp2; Function CDiv (const Cmp1, Cmp2: TComplex): TComplex; Cmp3 := Cmp1 / Cmp2; Function CDivR (const Cmp1: TComplex; t: Extended): TComplex; Cmp2 := Cmp1 / t; (Cmp2.real = Cmp1.real/t Cmp2.imag = Cmp1.real/t) The next set of functions realizes the optimized functions VII. Square of the complex: Procedure CSqrV(var Cmp1: TComplex); Cmp1 := Cmp1^2; Function CSqr (Cmp1: TComplex): TComplex; Cmp2 := Cmp1^2; VIII. Third power of the complex: Procedure CTripleV(var Cmp1: TComplex); Cmp1 := Cmp1^3; Function CTriple (Cmp1: TComplex): TComplex; Cmp2 := Cmp1^3; IX. Fourth power of the complex: Procedure CFourV(var Cmp1: TComplex); Cmp1 := Cmp1^4; Function CFour (Cmp1: TComplex): TComplex; Cmp2 := Cmp1^4; X. Flip of the complex: Procedure CFlipV(var Cmp1: TComplex); Cmp1.real := Cmp1.imag; Cmp1.imag := Cmp1.real; Function CFlip (Cmp1: TComplex): TComplex; Cmp2.real := Cmp1.imag; Cmp2.imag := Cmp1.real; XI. Reversing of the complex value: Procedure CRevV (var Cmp1: TComplex); Cmp1 := 1/ Cmp1; Function CRev (const Cmp1: TComplex): TComplex; Cmp2 := 1/ Cmp1; XII. Another reversing: Procedure CRev2V(var Cmp1: TComplex; Cmp2: TComplex); Cmp1 := 1 / (Cmp1 - Cmp2); Function CRev2 (Cmp1,Cmp2: TComplex): TComplex; Cmp3 := 1 / (Cmp1 - Cmp2); XIII. Absolute value of complex: Procedure CAbsV(var Cmp1: TComplex); Cmp1.real := Abs(Cmp1.real); Cmp1.imag := Cmp1.imag; Function CAbs (Cmp1: TComplex): TComplex; Cmp2.real := Abs(Cmp1.real); Cmp2.imag := Cmp1.Imag; Procedure CAbs2V(var Cmp1: TComplex); Cmp1.real := Abs(Cmp1.real); Cmp1.imag := Abs(Cmp1.imag); Function CAbs2 (Cmp1: TComplex): TComplex; Cmp2.real := Abs(Cmp1.real); Cmp2.imag := Abs(Cmp1.Imag); XIV. Real or imag part of complex: Procedure CRealV(var Cmp1: TComplex); Cmp1.real := Cmp1.real; Cmp1.imag := 0; Function CReal (Cmp1: TComplex): TComplex; Cmp2.real := Cmp1.real; Cmp2.imag := 0; Procedure CImagV(var Cmp1: TComplex); Cmp1.real := Cmp1.imag; Cmp1.imag := 0; Function CImag (Cmp1: TComplex): TComplex; Cmp2.real := Cmp1.imag; Cmp2.imag := 0; XV. Squre root of the complex: Procedure CSqrtV(var Cmp1: TComplex); Cmp1 := Sqrt(Cmp1); Function CSqrt (Cmp1: TComplex): TComplex; Cmp2 := Sqrt(Cmp1); XVI. Exponent of the complex: Procedure CExpV (var Cmp1: TComplex); Cmp1 := Exp(Cmp1); Function CExp (Cmp1: TComplex): TComplex; Cmp2 := Exp(Cmp1); XVII. Logorithm of the complex: Procedure CLnV (var Cmp1: TComplex); Cmp1 := Ln(Cmp1); Function CLn (Cmp1: TComplex): TComplex; Cmp2 := Ln(Cmp1); XVIII. Raise complex to a real power Procedure CPowerRV(var Cmp1: TComplex; t: Extended); Cmp1 := Cmp1^t; Function CPowerR (const Cmp1:TComplex;t: Extended): TComplex; Cmp2 := Cmp1^t; Procedure CPowerRV2(var Cmp1: TComplex; t: Extended); Cmp1 := Cmp1^t; Function CPowerR2(const Cmp1:TComplex;t: Extended): TComplex; Cmp2 := Cmp1^t; XIX. Raise complex value to a complex power: Procedure CPowerV(var Cmp1: TComplex; Cmp2: TComplex); Cmp1 := Cmp1^Cmp2; Function CPower (Cmp1,Cmp2: TComplex): TComplex; Cmp3 := Cmp1^Cmp2; Procedure CPowerV2(var Cmp1: TComplex; Cmp2: TComplex); Cmp1 := Cmp1^Cmp2; Function CPower2(Cmp1,Cmp2: TComplex): TComplex; Cmp3 := Cmp1^Cmp2; Trigonometric functions XX. Sinus of the complex: Procedure CSinV (var Cmp1: TComplex); Cmp1 := Sin(Cmp1); Function CSin (Cmp1: TComplex): TComplex; Cmp2 := Sin(Cmp1); XXI. Cosinus of the complex: Procedure CCosV (var Cmp1: TComplex); Cmp1 := Cos(Cmp1); Function CCos (Cmp1: TComplex): TComplex; Cmp2 := Cos(Cmp1); XXII. Tangent of the complex: Procedure CTanV (var Cmp1: TComplex); Cmp1 := Tan(Cmp1); Function CTan (Cmp1: TComplex): TComplex; Cmp2 := Tan(Cmp1); XXIII. Cotangent of the complex: Procedure CCotanV (var Cmp1: TComplex); Cmp1 := Cotan(Cmp1); Function CCotan (Cmp1: TComplex): TComplex; Cmp2 := Cotan(Cmp1); XXIV. Hiperbolic sinus of the complex: Procedure CSinhV(var Cmp1: TComplex); Cmp1 := Sinh(Cmp1); Function CSinh (Cmp1: TComplex): TComplex; Cmp2 := Sinh(Cmp1); XXV. Hiperbolic cosinus of the complex: Procedure CConhV(var Cmp1: TComplex); Cmp1 := Cosh(Cmp1); Function CCosh (Cmp1: TComplex): TComplex; Cmp2 := Cosh(Cmp1); XXVI. ArcSinus of the complex: Procedure CASinV (var Cmp1: TComplex); Cmp1 := ArcSin(Cmp1); Function CASin (const Cmp1: TComplex): TComplex; Cmp2 := ArcSin(Cmp1); XXVII. ArcCosinus of the complex: Procedure CACosV (var Cmp1: TComplex); Cmp1 := ArcCos(Cmp1); Function CACos (const Cmp1: TComplex): TComplex; Cmp2 := ArcCos(Cmp1); XXVIII. ArcTangens of the complex: Procedure CATanV (var Cmp1: TComplex); Cmp1 := ArcTan(Cmp1); Function CATan (const Cmp1: TComplex): TComplex; Cmp2 := ArcTan(Cmp1); XXIX. Gyperbolic arcsinus of the complex: Procedure CASinhV (var Cmp1: TComplex); Cmp1 := ArcSinh(Cmp1); Function CASinh (const Cmp1: TComplex): TComplex; Cmp2 := ArcSinh(Cmp1); XXX. Hyperbolic arccosinus of the complex: Procedure CACoshV (var Cmp1: TComplex); Cmp1 := ArcCosh(Cmp1); Function CACosh (const Cmp1: TComplex): TComplex; Cmp2 := ArcCosh(Cmp1); XXXI. Hyperbolic arctangent of the complex: Procedure CATanhV (var Cmp1: TComplex); Cmp1 := ArcTanh(Cmp1); Function CATanh (const Cmp1: TComplex): TComplex; Cmp2 := ArcTanh(Cmp1); Additional functions XXXII. Changes sign of imaginary part of the complex value Result.real := Cmp1.real; Result.imag :=-Cmp1.imag; Procedure CConjV (var Cmp1: TComplex); Function CConj (const Cmp1: TComplex): TComplex; 5.2 Functions selectorsFrom the "Select fractal" window two functions can be changed. These changes does not require re-compilation of the formula. You can use in your formula one or two functions and change the fractal directly from the "Select fractal" dialogue. To support external functions selections the procedure FuncDisp is implemented: Procedure FuncDisp(const Fn: Integer; var Cmp1: TComplex);
In this procedure - Fn parameter is Fn1 or Fn2 variables, which is passed to formulae from the outside. For example, write in your formula: FuncDisp(Fn1, Z);
And you can change the first function to get changes in the formula. Examples of the Mandelbrot-set with functions selections: var Z,Z0: TComplex; Begin FuncDisp(Fn1, Z); // change source value of the Z variable Z :=CAdd( CSqr(Z), Ñ); // calculate the Mandel SetResult(x,y, Z); // store result to [x] and [y] variables End; FuncDisp is a procedure, which modify second parameter. In the many cases such modification is not good and formula writers needs to add additional commands for saving previous value of the modified variable. To reduce time of the formula executing the new function dispatcher was added: Function FuncDispF(const Fn: Integer; Cmp1: TComplex): TComplex;
Like FuncDisp procedure Fn is a selector number and can assume one of the two values: Fn1 or Fn2. Cmp1 is a complex variable, which is an argument of the selected function. Value of the Cmp1 does not changed. The example code, listed above, can be written as: Begin Z :=CAdd( CSqr( FuncDispF(Fn1, Z) ), Ñ); SetResult(x,y, Z); End;
I. Mandelbrot formula: var Z,Z0: TComplex; Begin Z :=MakeComplex(x,y); // make complex from [x] and [y] variables Z0:=MakeComplex(cr,ci); // make complex from [cr] and [ci] variables Z :=CAdd( CSqr(Z), Z0); // calculate the Mandel SetResult(x,y, Z); // store result to [x] and [y] variables End; II. Mandel/Talis formula: z_new = z*z + c; c_new = c*c/(c+P1) + z_new; Write: var Z,Z0,P1: TComplex; Begin Z :=MakeComplex(x,y); // make complex from [x] and [y] variables Z0:=MakeComplex(cr,ci); // make complex from [cr] and [ci] variables P1:=MakeComplex(p1r,p1i); // make complex from [p1r] and [p1i] variables Z :=CAdd( CSqr(Z), Z0); // calculates Z_NEW Z0:=CDiv(CSqr(Z0), CAdd(Z0,P1)) // Z' = C*C/(C+P1) Z0:=CAdd(Z0,Z); // C_NEW = Z'+Z_NEW SetResult(cr,ci, Z0); // store C_NEW to [cr] and [ci] variables SetResult(x,y, Z); // store Z_NEW to [x] and [y] variables End; Others, more difficult examples can be found in the FE.ZIP archive. They're placed into the "Formulas" subfolder.
Changes in versions 2.01 and 2.02
Procedure CAddR(Cmp1: TComplex; t: Extended): TComplex; Function CSubR(Cmp1: TComplex; t: Extended): TComplex; Procedure CMulR(Cmp1: TComplex; t: Extended): TComplex; Function CDivR(Cmp1: TComplex; t: Extended): TComplex; Procedure CPowerRV(var Cmp1: TComplex; t: Extended); Function CPowerR ( Cmp1: TComplex; t: Extended): TComplex; Procedure CCotanV( var Cmp1: TComplex); Function CCotan (const Cmp1: TComplex): TComplex; Procedure CASinV ( var Cmp1: TComplex); Function CASin (const Cmp1: TComplex): TComplex; Procedure CACosV ( var Cmp1: TComplex); Function CACos (const Cmp1: TComplex): TComplex; Procedure CATanV ( var Cmp1: TComplex); Function CATan (const Cmp1: TComplex): TComplex; Procedure CASinhV( var Cmp1: TComplex); Function CASinh (const Cmp1: TComplex): TComplex; Procedure CACoshV( var Cmp1: TComplex); Function CACosh (const Cmp1: TComplex): TComplex; Procedure CATanhV( var Cmp1: TComplex); Function CATanh (const Cmp1: TComplex): TComplex;
Procedure Formula(var x, y, cr, ci: Extended; const p1r, p1i, p2r, p2i, p3r, p3i: Extended; var cA1, cA2, cA3, cA4: TComplex; const Fn1, Fn2: Integer); export;
Changes in version 2.03
Procedure Formula(var x, y, cr, ci: Extended; const p1r, p1i, p2r, p2i, p3r, p3i, p4r, p4i: Extended; var cA1, cA2, cA3, cA4: TComplex; const CPixel: TComplex; const Fn1, Fn2: Integer); export;
Procedure CConjV(Cmp1: TComplex); Function CConj(Cmp1: TComplex): TComplex; Jule 23, 2002:
September 26, 2004:
January 12, 2005:
Procedure CPowerV2(var Cmp1: TComplex; Cmp2: TComplex); Function CPower2 (Cmp1,Cmp2: TComplex): TComplex; Procedure CPowerRV2(var Cmp1: TComplex; t: Extended); Function CPowerR2 (Cmp1:TComplex;t: Extended): TComplex; |