In my opinion, cardioid checking (and testing for the low order buds) isn't a very useful strategy for optimising the calculation of the Mandelbrot fractal. This technique is only good for very low zooms, which only require a low number of iterations and are therefore fast without any optimisation.
More effective techniques for optimising the calculation (that work at higher zoom levels) are periodicity checking (also known as obit detection) and adjacency optimisation. I recommend having a read of Robert Munafo's Encyclopedia of the Mandelbrot Set:
http://mrob.com/pub/muency.html . He describes various techniques for adjacency optimisation: Solid guessing (successive refinement), boundary tracing and Mariani / Silver (also known as tesseral). All these techniques will help speed up the calculation inside the set (the black area).
There are two approaches to periodicity checking, one of which is described on Robert's website (the RHOP algorithm, the other being the binary back off algorithm). Both techniques will add overhead to the calculation but will greatly speed up detecting points inside the set. I believe the RHOP algorithm is faster than the BBO algorithm, but adds greater overhead (could be wrong though). I use the latter algorithm in my Mandelbrot program.
I have also found this page with a listing in Java, which you may find useful (includes cardioid / bulb detection and period checking - using the binary back off algorithm):
http://en.wikipedia.org/wiki/User:Simpsons_contributor/periodicity_checkingzenzero-2001
I agree with zenzero about the cardioid optimization being of very limited usefulness. I did a lot of research on various heuristics for Mandelbrot sets, and finally settled on using a boundary following algorithm.
The Mandelbrot set is connected, and so are the iteration bands around it. The connections are infinitely thin, and not detectable at any given scale, but you can be sure that "blobs" of Mandelbrot points will never contain non-mandelbrot points inside. You can therefore walk the outside of any group of Mandelbrot pictures, always turning in the same direction (a common maze solving algorithm) Then, once you get back to your starting point, you can flood-fill the inside.
This also works for any iteration band surrounding the Mandelbrot set. The deeper the zoom the less useful boundary following tends to be for non-Mandelbrot points, but it is even
more useful for Mandelbrot points because you typically need to increase the max iteration count for deeper zooms, so points that are members of the Mandelbrot set become very expensive to calculate.
Boundary following works for ANY portion of the Mandelbrot set (with varying degrees of success), whereas plotting known shapes like the main cardioid , "Baby Mandelbrot" cardioid", and main disks only works for zooms that include those small numbers of shapes.
My application, FractalWorks, includes boundary following as well as multi-threading and symmetry calculations. I even got boundary following working for Julia sets. I found through testing that even for "Fatou Dust" plots (disconnected Julia set plots who's origin point is not a Mandelbrot point) I can create perfect plots without any holes if I start boundary following above 10 or 15 iterations.
I got the idea for boundary following from Dr. Evgeny Demidov, who wrote a VERY impressive
Mandelbrot and Julia set renderers for the web in Java that was dramatically faster than early versions of FractalWorks. He published the source code for his Java program, which gave me enough information to implement my own boundary following algorithm.
FractalWorks has preferences that let you turn boundary following on and off, and tracks the total pixels and iterations calculated vs. those skipped because of boundary following. For plots that have large blobs of Mandelbrot points, the effect can be quite dramatic. It can give 10-fold or better improvements in speed.
If you request Distance Estimate or fractional iteration values for a plot, the program can't use boundary following for any points except Mandelbrot/Julia set points, but that is still a big win for any plot that has any "Baby Mandelbrots" in it.
FractalWorks doesn't support orbit trap coloring of Mandelbrot points, so I can always use boundary following for those points. If you wanted to use orbit trap calculations you would probably have to brute-force Mandelbrot points.
FractalWorks is only available for Macintoshes. It's available in the Mac App Store (MAS) if you're interested in trying it out. Here's the link:
FractalWorks in the Mac App StoreFractalWorks requires Mac OS 10.6.6 or later.
-----
EDIT:
I did a benchmark plot of the whole Mandelbrot set (real width 3.0) at 10,000 max iterations.
With boundary following and symmetry turned off, it took 7.583 seconds, and required calculating 1,089,686,150 iterations.
With boundary following turned on (and symmetry still turned off) the same plot takes between 0.25 seconds and and 0.367 seconds. (At plot times that short, things like screen refreshing and when the app gets swapped into the background have a disproportionately large effect on plot times, so the recorded plot times can vary by a fair margin.). The plot required calculating 59,855,336 iterations, or about 5.5% of the total iterations for the brute force method.
Zooms into the cleft of Seahorse Valley or one of the cardioids can have even more dramatic speedups. I just did a plot of the cleft of the main cardioid that's mostly black with boundary following turned on, and FractalWorks is able to skip 98.93% of the total iterations that would be required for the "brute force" approach. If I were to turn symmetry calculations back on for that plot the speed roughly doubles again. These speedups work for the main body of the Mandelbrot set, or for any of the "Baby Mandelbrots"