Example #1
0
    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);
    }
Example #2
0
 public bool IsInside(EscapeTime escapeTime)
 {
     if (escapeTime.IsInfinite)
     {
         return(false);
     }
     return(IsInside(escapeTime.Iterations));
 }
Example #3
0
    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]);
        }
    }
Example #4
0
    /// <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));
    }
Example #5
0
    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);
    }
Example #6
0
    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());
    }
}