public static EscapeTime FindEscapeTimeNoCycleDetection(Complex c, int maxIterations) { if (MandelbulbChecker.IsInsideBulbs(c)) { return(EscapeTime.Infinite); } var zReal = 0.0; var zImag = 0.0; var z2Real = 0.0; var z2Imag = 0.0; for (int i = 0; i < maxIterations; i++) { zImag = 2 * zReal * zImag + c.Imaginary; zReal = z2Real - z2Imag + c.Real; z2Real = zReal * zReal; z2Imag = zImag * zImag; if ((z2Real + z2Imag) > 4) { return(EscapeTime.Discrete(i)); } } return(EscapeTime.Infinite); }
public bool IsInside(EscapeTime escapeTime) { if (escapeTime.IsInfinite) { return(false); } return(IsInside(escapeTime.Iterations)); }
public static void FindEscapeTimes(double[] cReals, double[] cImags, int maxIterations, EscapeTime[] escapeTimes) { var cReal = new Vector <double>(cReals); var cImag = new Vector <double>(cImags); var vIterations = IteratePoints(cReal, cImag, maxIterations); for (int i = 0; i < Capacity; i++) { escapeTimes[i] = EscapeTime.Choose((int)vIterations[i]); } }
/// <summary> /// Determines whether the point is in the set, without using an arbitrary iteration limit. /// </summary> /// <param name="c">The c.</param> /// <remarks> /// Brent's Algorithm is used to detect cycles for points in the set. /// </remarks> /// <returns> /// The <see cref="EscapeTime"/> of the point. /// </returns> public static EscapeTime FindEscapeTime(Complex c) { if (MandelbulbChecker.IsInsideBulbs(c)) { return(EscapeTime.Infinite); } var zReal = 0.0f; var zImag = 0.0f; var z2Real = 0.0f; var z2Imag = 0.0f; var oldZReal = 0.0f; var oldZImag = 0.0f; var cReal = (float)c.Real; var cImag = (float)c.Imaginary; int stepsTaken = 0; int stepLimit = 2; int iterations = 0; while ((z2Real + z2Imag) <= 4) { iterations++; stepsTaken++; zImag = 2 * zReal * zImag + cImag; zReal = z2Real - z2Imag + cReal; z2Real = zReal * zReal; z2Imag = zImag * zImag; if (oldZReal == zReal && oldZImag == zImag) { return(EscapeTime.Infinite); } if (stepsTaken == stepLimit) { oldZReal = zReal; oldZImag = zImag; stepsTaken = 0; stepLimit = stepLimit << 1; } } return(EscapeTime.Discrete(iterations)); }
public static EscapeTime FindEscapeTime(Complex c, int maxIterations) { if (MandelbulbChecker.IsInsideBulbs(c)) { return(EscapeTime.Infinite); } var zReal = 0.0f; var zImag = 0.0f; var z2Real = 0.0f; var z2Imag = 0.0f; var oldZReal = 0.0f; var oldZImag = 0.0f; int stepsTaken = 0; int stepLimit = 2; for (int i = 0; i < maxIterations; i++) { stepsTaken++; zImag = 2 * zReal * zImag + (float)c.Imaginary; zReal = z2Real - z2Imag + (float)c.Real; if (oldZReal == zReal && oldZImag == zImag) { return(EscapeTime.Infinite); } z2Real = zReal * zReal; z2Imag = zImag * zImag; if ((z2Real + z2Imag) > 4) { return(EscapeTime.Discrete(i)); } if (stepsTaken == stepLimit) { oldZReal = zReal; oldZImag = zImag; stepsTaken = 0; stepLimit = stepLimit << 1; } } return(EscapeTime.Infinite); }
public static void Compute( string filePath, ViewPort viewPort, ComputationType computationType, CancellationToken token) { Log.Info($"Outputting to: {filePath}"); Log.Info($"Resolution: {viewPort.Resolution.Width:N0}x{viewPort.Resolution.Height:N0}"); Log.Info($"Area: {viewPort.Area}"); Log.Info($"Computation type: {computationType}"); IEnumerable <bool> GetPointsInSetScalar() { var kernel = KernelBuilder.BuildScalarKernel(computationType); var rowPointsInSet = new bool[viewPort.Resolution.Width]; using var progress = TimedOperation.Start("points", totalWork: viewPort.Resolution.Area()); for (int row = 0; row < viewPort.Resolution.Height; row++) { Parallel.For( 0, viewPort.Resolution.Width, col => rowPointsInSet[col] = kernel.FindEscapeTime(viewPort.GetComplex(col, row), Constant.IterationRange.Max).IsInfinite); for (int x = 0; x < viewPort.Resolution.Width; x++) { yield return(rowPointsInSet[x]); } progress.AddWorkDone(viewPort.Resolution.Width); } } IEnumerable <bool> GetPointsInSetVectorDoubles() { using var progress = TimedOperation.Start("points", totalWork: viewPort.Resolution.Area()); var vWidth = VectorDoubleKernel.Capacity; var vectorBatches = viewPort.Resolution.Width / vWidth; var remainder = viewPort.Resolution.Width % vWidth; if (remainder != 0) { vectorBatches++; } var lastIndex = vectorBatches - 1; var rowPointsInSet = new bool[viewPort.Resolution.Width]; // TODO: Why is the Parallel.For inside a loop? for (int row = 0; row < viewPort.Resolution.Height; row++) { Parallel.For( 0, vectorBatches, batchIndex => { var realBatch = new double[vWidth]; var imagBatch = new double[vWidth]; var times = new EscapeTime[vWidth]; var batchSize = (batchIndex == lastIndex) ? remainder : vWidth; for (int i = 0; i < batchSize; i++) { var c = viewPort.GetComplex(batchIndex * vWidth + i, row); realBatch[i] = c.Real; imagBatch[i] = c.Imaginary; } VectorDoubleKernel.FindEscapeTimes( realBatch, imagBatch, Constant.IterationRange.Max, times); for (int i = 0; i < batchSize; i++) { rowPointsInSet[batchIndex * vWidth + i] = times[i].Iterations == Constant.IterationRange.Max; } }); for (int x = 0; x < viewPort.Resolution.Width; x++) { yield return(rowPointsInSet[x]); } progress.AddWorkDone(viewPort.Resolution.Width); } } IEnumerable <bool> ChooseEnumerator() => computationType switch { ComputationType.ScalarDouble => GetPointsInSetScalar(), ComputationType.ScalarFloat => GetPointsInSetScalar(), ComputationType.VectorDouble => GetPointsInSetVectorDoubles(), _ => throw new ArgumentException("Unsupported computation type: " + computationType) }; Write(filePath, viewPort, computationType, ChooseEnumerator()); } }