// ====================================================================== // W space - Exp Z fractal (CC) 2008 Jens Koeplinger // License: Creative Commons Attribution "Share Alike 3.0 Unported" // http://creativecommons.org/licenses/by-sa/3.0 // See main file "wspaceexpfractal.c" for what this means to you! // ====================================================================== // lib-wspaceexpfractal-Plot.h // ---------------------------------------------------------------------- // This library takes the incoming, prepared Y(n) pyramid (i.e. each // point in each level has been divided by n!, and all min- and max- // contributions from every level on down have been calculated), and // plots it, by adding through each possible combination of points, // with one point from each level. Calculation will be aborted when // values cannot contribute to the plottable area anymore. // // Example of use: /* plotExpZFractal(); */ // ---------------------------------------------------------------------- void plotExpZFractal() { // From each level in the Y(n) pyramid, one point is selected // to calculate the final result set. The calculation is done // revursively, but entire recusrion branches are pruned when // their horizontal and vertical minimum and maximum contributions // could never add up to a point within the plottable area. // // IN: xMin, xMax left-, right-parameter bound of plottable area // yMin, yMax lower-, upper-parameter bound of plottable area // totalPyramidDepth number (and pointer) of deepest level // totalPyramidPoints pointer to the hightest point index // YnR[point], YnW[point] real and W parts of each point // YnLevelPtr[level] pointer to first point in each level // OUT: YnLevel{X|Y}{Min|Max}[level] // min/max left-/right-/lower-/upper-parameter bound // from [level] and deeper int curLevelPoint[maxPyramidDepth]; // pointer to current point at each level double curLevelSumR[maxPyramidDepth]; // throwaway storage of point sum down to double curLevelSumW[maxPyramidDepth]; // a certain level (real and W) int curLevel; // current level int curPoint; // current point double curR; // throwaway current sum, real part double curW; // ... W part int exitCondition; // throwaway recursion exit int crawlNext; // if true, indicates to crawl next/up // (otherwise, it will crawl down) int crawlUp; int pointsPlotted; // counter of actual points set int pointsPlottedBillions; // ... and a billions-overflow counter int lvl5count; // approximate progress counter sprintf(logTxt, "Plot all points recursively.\n"); writeLog(); // seed the recursion: begin at the highest point in the pyramid, // and crawl all combinations curLevelPoint[0] = YnLevelPtr[0]; curLevelSumR[0] = YnR[curLevelPoint[0]]; curLevelSumW[0] = YnW[curLevelPoint[0]]; curLevelPoint[1] = YnLevelPtr[1]; curLevel = 1; exitCondition = 0; pointsPlotted = 0; pointsPlottedBillions = 0; lvl5count = 0; // on a large enough recursion, level 4 gets entered 64 times // => use as percent complete counter // all values are seeded; begin recursion while (exitCondition == 0) { // crawl the pyramid: // - get the next point for processing at the current level // - calculate current point // - if deepest level reached: // - - if point in bounds, plot // - - advance pointer to next point in level, or crawl up // - - start over (or exit recursion if end) // - not deepest level; determine whether could be in-bounds for the plot // - if no plot contribution possible: // - - advance pointer to next point in level, or crawl up // - - start over (or exit recursion if end) // - contribution is possible; increase level // - set pointer to first point in new (deeper) level curPoint = curLevelPoint[curLevel]; curR = YnR[curPoint] + curLevelSumR[curLevel - 1]; curW = YnW[curPoint] + curLevelSumW[curLevel - 1]; crawlNext = false; if (DEBUG) { sprintf(logTxt, " [DEBUG 10] level: %d, point: %d, plotted: %d\n", curLevel, curPoint, pointsPlotted); writeLog(); } if (curLevel == totalPyramidDepth) { // this is the deepest level: // - try to plot the point // - crawl to next if (DEBUG) { sprintf(logTxt, " [DEBUG 11] plot: %le, %le\n", curR, curW); writeLog(); } setPointOnBitmap(curR, curW); pointsPlotted++; if (pointsPlotted > 1000000000) { pointsPlottedBillions++; pointsPlotted = 1; } crawlNext = true; } else { // not at the deepest level yet; check boundaries if ((curR + YnLevelXMax[curLevel + 1]) < xMin) { // will always be to the left of the plot; no need to advance crawlNext = true; } else if ((curR + YnLevelXMin[curLevel + 1]) > xMax) { // will always be to the right of plot crawlNext = true; } else if ((curW + YnLevelYMax[curLevel + 1]) < yMin) { // will always be below crawlNext = true; } else if ((curW + YnLevelYMin[curLevel + 1]) > yMax) { // will always be above crawlNext = true; } } // point is plotted (if any); and checks are done. // see whether we advance to the next point (crawlNext = true) // or whether to drill down deeper into the pyramid (false). if (crawlNext) { // move to the next point of this level (if any); // otherwise, crawl up the pyramid to find the next point if (DEBUG) { sprintf(logTxt, " [DEBUG 12] crawl next\n"); writeLog(); } crawlUp = true; while (crawlUp == true) { crawlUp = false; curPoint++; if (curLevel == totalPyramidDepth) { // at the deepest level if (curPoint > totalPyramidPoints) { // end of pyramid reached; crawl up crawlUp = true; } } else if (curPoint >= YnLevelPtr[curLevel + 1]) { // end of level reached; crawl up crawlUp = true; } if (crawlUp) { // flag for crawling up the pyramid set: // - decrease level by one // - if level = 0 then set exitCondition = 0 and stop (crawlUp = false) curLevel--; if (curLevel == 0) { // finished!!! yeah! exitCondition = 1; // done crawlUp = false; } else { // get the point that we previously came // from that level curPoint = curLevelPoint[curLevel]; } } else { // point found; record and proceed curLevelPoint[curLevel] = curPoint; crawlUp = false; } } } else { // go one level deeper into the pyramid: // - keep the sum so far in the throwaway arrays for this level // - go to the next deeper level // - set pointer to first point in level if (DEBUG) { sprintf(logTxt, " [DEBUG 13] go deeper\n"); writeLog(); } curLevelSumR[curLevel] = curR; curLevelSumW[curLevel] = curW; curLevel++; curLevelPoint[curLevel] = YnLevelPtr[curLevel]; if (curLevel == 5) { // on a typical (non-tiny) computation, level 4 gets // entered 64 times; use as rough "percent complete" // indicator sprintf(logTxt, "[INFO] (run ID=%d) Approximate progress: %d percent\n", runID, (int) (((double) lvl5count) / 0.64)); writeLog(); sprintf(logTxt, "[INFO] points plotted so far: %d billion and %d\n", pointsPlottedBillions, pointsPlotted); writeLog(); writeTimeToLog(); lvl5count++; } } } // done! sprintf(logTxt, "All points have been plotted.\n"); writeLog(); sprintf(logTxt, "- total points plotted: %d billion and %d\n", pointsPlottedBillions, pointsPlotted); writeLog(); }