Here is an *ATTEMPTED* explanation of what the inside=bof60 and inside=bof61 options do. This explanation is hereby dedicated to Adrian Mariano, who badgered it out of us! For the *REAL* explanation, see "Beauty of Fractals", page 62.
Let p(z) be the function that is repeatedly iterated to generate a fractal using the escape-time algorithm. For example, p(z) = z^2+c in the case of a Julia set. Then let pk(z) be the result of iterating the function p for k iterations. (The "k" should be shown as a superscript.) We could also use the notation pkc(z) when the function p has a parameter c, as it does in our example. Now hold your breath and get your thinking cap on. Define a(c) = inf{|pkc(0)|:k=1,2,3,...}. In English - a(c) is the greatest lower bound of the images of zero of as many iterations as you like. Put another way, a(c) is the closest to the origin any point in the orbit starting with 0 gets. Then the index (c) is the value of k (the iteration) when that closest point was achieved. Since there may be more than one, index(c) is the least such. Got it? Good, because the "Beauty of Fractals" explanation of this, is, ahhhh, *TERSE* ! Now for the punch line. Inside=bof60 colors the lake alternating shades according to the level sets of a(c). Each band represents solid areas of the fractal where the closest value of the orbit to the origin is the same. Inside=bof61 show domains where index(c) is constant. That is, areas where the iteration when the orbit swooped closest to the origin has the same value. Well, folks, that's the best we can do! Improved explanations will be accepted for the next edition!
In response to this request for lucidity, Herb Savage offers this explanation the bof60 and bof61 options:
The picture on page 60 of The Beauty of Fractals shows the distance to origin of the closest point to the origin in the sequence of points generated from a given X,Y coordinate. The picture on page 61 shows the index (or number) in the sequence of the closest point.
is similar. This option colors inside pixels according to the magnitude of the orbit point when maxiter was reached, using the formula color = (x^2 + y^2) * maxiter/2 + 1.
colors inside pixels according to the magnitude of the last orbit point which within a set distance from the origin. Then: color = magnitude * colors / closeprox The value of closeprox can be varied interactively. This feature was contributed by Iain Stirling.
colors pixels according to the length of their eventual cycle. For example, points that approach a fixed point have color=1. Points that approach a 2-cycle have color=2. Points that do not approach a cycle during the iterations performed have color=maxit. This option works best with a fairly large number of iterations.
colors by determining the angle in degrees the last iterated value has with respect to the real axis, and using the absolute value. This feature should be used with periodicity=0
Kenneth Hooper has written a paper entitled "A Note On Some Internal Structures Of The Mandelbrot Set" published in "Computers and Graphics", Vol 15, No.2, pp. 295-297. In that article he describes Clifford Pickover's "epsilon cross" method which creates some mysterious plant- like tendrils in the Mandelbrot set. The algorithm is this. In the escape-time calculation of a fractal, if the orbit comes within .01 of the Y-axis, the orbit is terminated and the pixel is colored green. Similarly, the pixel is colored yellow if it approaches the X-axis. Strictly speaking, this is not an "inside" option because a point destined to escape could be caught by this bailout criterion.
The test distance, 0.01, can now be changed interactively on the <x> screen and via the proximity=<nnn> command line parameter. A negative value of the test distance triggers an alternative variation of epsilon cross that colors the epsilon bands with the iteration; otherwise they are colored normally to maintain compatibility.
Hooper has another coloring scheme called "star trails" that involves detecting clusters of points being traversed by the orbit. A table of tangents of each orbit point is built, and the pixel colored according to how many orbit points are near the first one before the orbit flies out of the cluster. This option looks fine with maxiter=16, which greatly speeds the calculation.
Both of these options should be tried with the outside color fixed (outside=[nnn]) so that the "lake" structure revealed by the algorithms can be more clearly seen. Epsilon Cross is fun to watch with boundary tracing turned on - even though the result is incorrect it is interesting! Shucks - what does "incorrect" mean in chaos theory anyway?!
Many of Fractint's fractals involve the iteration of functions of complex numbers until some "bailout" value is exceeded, then coloring the associated pixel according to the number of iterations performed. This process identifies which values tend to infinity when iterated, and gives us a rough measure of how "quickly" they get there.
In dynamical terms, we say that "Infinity is an Attractor", as many initial values get "attracted" to it when iterated. The set of all points that are attracted to infinity is termed The Basin of Attraction of Infinity. The coloring algorithm used divides this Basin of Attraction into many distinct sets, each a single band of one color, representing all the points that are "attracted" to Infinity at the same "rate". These sets (bands of color) are termed "Level Sets" - all points in such a set are at the same "Level" away from the attractor, in terms of numbers of iterations required to exceed the bailout value.
Thus, Fractint produces colored images of the Level Sets of the Basin of Attraction of Infinity, for all fractals that iterate functions of Complex numbers, at least. Now we have a sound mathematical definition of what Fractint's "bailout" processing generates, and we have formally introduced the terms Attractor, Basin of Attraction, and Level Set, so you should have little trouble following the rest of this section!
For certain Julia-type fractals, Fractint can also display the Level Sets of Basins of Attraction of Finite Attractors. This capability is a by-product of the implementation of the MAGNETic fractal types, which always have at least one Finite Attractor.
This option can be invoked by setting the "Look for finite attractor" option on the [Y] options screen, or by giving the "finattract=yes" command-line option.
Most Julia-types that have a "lake" (normally colored blue by default) have a Finite Attractor within this lake, and the lake turns out to be, quite appropriately, the Basin of Attraction of this Attractor. The "finattract=yes" option (command-line or [Y] options screen) instructs Fractint to seek out and identify a possible Finite Attractor and, if found, to display the Level Sets of its Basin of Attraction, in addition to those of the Basin of Attraction of Infinity. In many cases this results in a "lake" with colored "waves" in it; in other cases there may be little change in the lake's appearance.
For a quick demonstration, select a fractal type of LAMBDA, with a parameter of 0.5 + 0.5i. You will obtain an image with a large blue lake. Now set "Look for finite attractor" to 1 with the "Y" menu. The image will be re-drawn with a much more colorful lake. A Finite Attractor lives in the center of one of the resulting "ripple" patterns in the lake - turn the [O]rbits display on to see where it is - the orbits of all initial points that are in the lake converge there.
Fractint tests for the presence of a Finite Attractor by iterating a Critical Value of the fractal's function. If the iteration doesn't bail out before exceeding twice the iteration limit, it is almost certain that we have a Finite Attractor - we assume that we have.
Next we define a small circle around it and, after each iteration, as well as testing for the usual bailout value being exceeded, we test to see if we've hit the circle. If so, we bail out and color our pixels according to the number of iterations performed. Result - a nicely colored-in lake that displays the Level Sets of the Basin of Attraction of the Finite Attractor. Sometimes !
First exception: This does not work for the lakes of Mandel-types. Every point in a Mandel-type is, in effect, a single point plucked from one of its related Julia-types. A Mandel-type's lake has an infinite number of points, and thus an infinite number of related Julia-type sets, and consequently an infinite number of finite attractors too. It *MAY* be possible to color in such a lake, by determining the attractor for EVERY pixel, but this would probably treble (at least) the number of iterations needed to draw the image. Due to this overhead, Finite Attractor logic has not been implemented for Mandel-types.
Secondly, certain Julia-types with lakes may not respond to this treatment, depending on the parameter value used. E.g., the Lambda Set for 0.5 + 0.5i responds well; the Lambda Set for 0.0 + 1.0i does not - its lake stays blue. Attractors that consist of single points, or a cycle of a finite number of points are ok. Others are not. If you're into fractal technospeak, the implemented approach fails if the Julia- type is a Parabolic case, or has Siegel Disks, or has Herman Rings.
However, all the difficult cases have one thing in common - they all have a parameter value that falls exactly on the edge of the related Mandel-type's lake. You can avoid them by intelligent use of the Mandel-Julia Space-Bar toggle: Pick a view of the related Mandel-type where the center of the screen is inside the lake, but not too close to its edge, then use the space-bar toggle. You should obtain a usable Julia-type with a lake, if you follow this guideline.
Thirdly, the initial implementation only works for Julia-types that use the "Standard" fractal engine in Fractint. Fractals with their own special algorithms are not affected by Finite Attractor logic, as yet. Finally, the finite attractor code will not work if it fails to detect a finite attractor. If the number of iterations is set too low, the finite attractor may be missed.
Despite these restrictions, the Finite Attractor logic can produce interesting results. Just bear in mind that it is principally a bonus off-shoot from the development of the MAGNETic fractal types, and is not specifically tuned for optimal performance for other Julia types.
(Thanks to Kevin Allen for the above).
There is a second type of finite attractor coloring, which is selected by setting "Look for Finite Attractor" to a negative value. This colors points by the phase of the convergence to the finite attractor, instead of by the speed of convergence.
For example, consider the Julia set for -0.1 + 0.7i, which is the three- lobed "rabbit" set. The Finite Attractor is an orbit of length three; call these values a, b, and c. Then, the Julia set iteration can converge to one of three sequences: a,b,c,a,b,c,..., or b,c,a,b,c,..., or c,a,b,c,a,b,... The Finite Attractor phase option colors the interior of the Julia set with three colors, depending on which of the three sequences the orbit converges to. Internally, the code determines one point of the orbit, say "a", and the length of the orbit cycle, say 3. It then iterates until the sequence converges to a, and then uses the iteration number modulo 3 to determine the color.
The following trig identities are invaluable for coding fractals that use complex-valued transcendental functions of a complex variable in terms of real-valued functions of a real variable, which are usually found in compiler math libraries. In what follows, we sometimes use "*" for multiplication, but leave it out when clarity is not lost. We use "^" for exponentiation; x^y is x to the y power.
(u+iv) + (x+iy) = (u+x) + i(v+y) (u+iv) - (x+iy) = (u-x) + i(v-y) (u+iv) * (x+iy) = (ux - vy) + i(vx + uy) (u+iv) / (x+iy) = ((ux + vy) + i(vx - uy)) / (x^2 + y^2) e^(x+iy) = (e^x) (cos(y) + i sin(y)) log(x+iy) = (1/2)log(x^2 + y^2) + i(atan(y/x) + 2kPi) for k = 0, -1, 1, -2, 2, ...(The log function refers to log base e, or ln. The expression atan(y/x) is an angle between -pi and pi in the quadrant containing (x,y) implemented in C as the atan2() function.)
z^w = e^(w*log(z)) sin(x+iy) = sin(x)cosh(y) + i cos(x)sinh(y) cos(x+iy) = cos(x)cosh(y) - i sin(x)sinh(y) tan(x+iy) = sin(x+iy) / cos(x+iy) sinh(x+iy) = sinh(x)cos(y) + i cosh(x)sin(y) cosh(x+iy) = cosh(x)cos(y) + i sinh(x)sin(y) tanh(x+iy) = sinh(x+iy) / cosh(x+iy) cosxx(x+iy) = cos(x)cosh(y) + i sin(x)sinh(y)(cosxx is present in Fractint to provide compatibility with a bug which was in its cos calculation before version 16)
sin(2x) sinh(2y) tan(x+iy) = ------------------ + i------------------ cos(2x) + cosh(2y) cos(2x) + cosh(2y) sin(2x) - i*sinh(2y) cotan(x+iy) = -------------------- cosh(2y) - cos(2x) sinh(2x) sin(2y) tanh(x+iy) = ------------------ + i------------------ cosh(2x) + cos(2y) cosh(2x) + cos(2y) sinh(2x) - i*sin(2y) cotanh(x+iy) = -------------------- cosh(2x) - cos(2y) asin(z) = -i * log(i*z+sqrt(1-z*z)) acos(z) = -i * log(z+sqrt(z*z-1)) atan(z) = i/2* log((1-i*z)/(1+i*z)) asinh(z) = log(z+sqrt(z*z+1)) acosh(z) = log(z+sqrt(z*z-1)) atanh(z) = 1/2 * log((1+z)/(1-z)) sqr(x+iy) = (x^2-y^2) + i*2xy sqrt(x+iy) = sqrt(sqrt(x^2+y^2)) * (cos(atan(y/x)/2) + i sin(atan(y/x)/2)) ident(x+iy) = x + iy conj(x+iy) = x - iy recip(x+iy) = (x-iy) / (x^2+y^2) flip(x+iy) = y + ix zero(x+iy) = 0 one(x+iy) = 1 cabs(x+iy) = sqrt(x^2 + y^2) floor(x+iy) = floor(x) + i*floor(y) ceil(x+iy) = ceil(x) + i*ceil(y) trunc(x+iy) = trunc(x) + i*trunc(y) round(x+iy) = round(x) + i*round(y)
Fractint's definitions of abs(x+iy) and |x+iy| below are non-standard. Math texts define both absolute value and modulus of a complex number to be the same thing. They are both equal to cabs(x+iy) as defined above.
|x+iy| = x^2 + y^2 abs(x+iy) = sqrt(x^2) + i sqrt(y^2)
Quaternions are four dimensional generalizations of complex numbers. They almost obey the familiar field properties of real numbers, but fail the commutative law of multiplication, since x*y is not generally equal to y*x.
Quaternion algebra is most compactly described by specifying the rules for multiplying the basis vectors 1, i, j, and k. Quaternions form a superset of the complex numbers, and the basis vectors 1 and i are the familiar basis vectors for the complex algebra. Any quaternion q can be represented as a linear combination q = x + yi + zj + wk of the basis vectors just as any complex number can be written in the form z = a + bi.
Multiplication rules for quaternion basis vectors:
ij = k jk = i ki = j ji = -k kj = -i ik = -j ii = jj = kk = -1 ijk = -1
Note that ij = k but ji = -k, showing the failure of the commutative law. The rules for multiplying any two quaternions follow from the behavior of the basis vectors just described. However, for your convenience, the following formula works out the details.
Let q1 = x1 + y1i + z1j + w1k and q2 = x2 + y2i + z2j + w2k. Then q1q2 = 1(x1x2 - y1y2 - z1z2 - w1w2) + i(y1x2 + x1y2 + w1z2 - z1w2) + j(z1x2 - w1y2 + x1z2 + y1w2) + k(w1x2 + z1y2 - y1z2 + x1w2)
Quaternions are not the only possible four dimensional supersets of the complex numbers. William Rowan Hamilton, who discovered quaternions in 1843, considered the alternative called the hypercomplex number system. Unlike quaternions, the hypercomplex numbers satisfy the commutative law of multiplication. The law which fails is the field property that states that all non-zero elements of a field have a multiplicative inverse. For a non-zero hypercomplex number h, the multiplicative inverse 1/h does not always exist.
As with quaternions, we will define multiplication in terms of the basis vectors 1, i, j, and k, but with subtly different rules.
Multiplication rules for hypercomplex basis vectors:
ij = k jk = -i ki = -j ji = k kj = -i ik = -j ii = jj = -kk = -1 ijk = 1
Note that now ij = k and ji = k, and similarly for other products of pairs of basis vectors, so the commutative law holds.
Hypercomplex multiplication formula:
Let h1 = x1 + y1i + z1j + w1k and h2 = x2 + y2i + z2j + w2k. Then h1h2 = 1(x1x2 - y1y2 - z1z2 + w1w2) + i(y1x2 + x1y2 - w1z2 - z1w2) + j(z1x2 - w1y2 + x1z2 - y1w2) + k(w1x2 + z1y2 + y1z2 + x1w2)
As an added bonus, we'll give you the formula for the reciprocal.
Let det = [((x-w)^2+(y+z)^2)((x+w)^2+(y-z)^2)] Then 1/h = 1[ x(x^2+y^2+z^2+w^2)-2w(xw-yz)]/det + i[-y(x^2+y^2+z^2+w^2)-2z(xw-yz)]/det + j[-z(x^2+y^2+z^2+w^2)-2y(xw-yz)]/det + k[ w(x^2+y^2+z^2+w^2)-2x(xw-yz)]/det
A look at this formula shows the difficulty with hypercomplex numbers. In order to calculate 1/h, you have to divide by the quantity det = [((x-w)^2+(y+z)^2)((x+w)^2+(y-z)^2)]. So when this quantity is zero, the multiplicative inverse will not exist.
Hypercomplex numbers numbers have an elegant generalization of any unary complex valued function defined on the complex numbers. First, note that hypercomplex numbers can be represented as a pair of complex numbers in the following way.
Let h = x + yi + zj + wk. a = (x-w) + i(y+z) b = (x+w) + i(y-z)
The numbers a and b are complex numbers. We can represent h as the pair of complex numbers (a,b). Conversely, if we have a hypercomplex number given to us in the form (a,b), we can solve for x, y, z, and w. The solution to
c = (x-w) + i(y+z) d = (x+w) + i(y-z)is
x = (real(c) + real(d))/2 y = (imag(c) + imag(d))/2 z = (imag(c) - imag(d))/2 w = (real(d) - real(c))/2
We can now, for example, compute sin(h). First compute the two complex numbers a and b as above, then set c = sin(a) and d = sin(b) where sin() is the complex version of the sin function. Now use the equations above to solve for x, y, z, and w in terms of c and d. The hypercomplex number (x,y,z,w) thus obtained is sin(h).
The beauty of this is that it really doesn't make any difference what function we use. Instead of sin, we could have used cos, sinh, ln, or z^2. Using this technique, Fractint can create 3-D fractals using the formula h' = fn(h) + c, where "fn" is any of the built-in functions. Where fn is sqr(), this is the famous mandelbrot formula, generalized to four dimensions.
For more information, see _Fractal Creations, Second Edition_ by Tim Wegner and Bert Tyler, Waite Group Press, 1993.