Пример #1
0
        // Render the fractal on a single thread using the ComplexFloatVec data type
        // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
        public void RenderSingleThreadedWithADT(float xmin, float xmax, float ymin, float ymax, float step)
        {
            Vector <float> vmax_iters = new Vector <float>((float)max_iters);
            Vector <float> vlimit     = new Vector <float>(limit);
            Vector <float> vstep      = new Vector <float>(step);
            Vector <float> vxmax      = new Vector <float>(xmax);
            Vector <float> vinc       = new Vector <float>((float)Vector <float> .Count * step);
            Vector <float> vxmin      = VectorHelper.Create(i => xmin + step * i);

            float y  = ymin;
            int   yp = 0;

            for (Vector <float> vy = new Vector <float>(ymin); y <= ymax && !Abort; vy += vstep, y += step, yp++)
            {
                int xp = 0;
                for (Vector <float> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector <float> .Count)
                {
                    ComplexVecFloat num   = new ComplexVecFloat(vx, vy);
                    ComplexVecFloat accum = num;

                    Vector <float> viters    = Vector <float> .Zero;
                    Vector <float> increment = Vector <float> .One;
                    do
                    {
                        accum   = accum.square() + num;
                        viters += increment;
                        Vector <float> vCond = Vector.LessThanOrEqual <float>(accum.sqabs(), vlimit) &
                                               Vector.LessThanOrEqual <float>(viters, vmax_iters);
                        increment = increment & vCond;
                    } while (increment != Vector <float> .Zero);

                    viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
                }
            }
        }
Пример #2
0
        // Render the fractal on multiple threads using raw Vector<double> data types
        // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
        public void RenderMultiThreadedNoADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
        {
            double xmin = (double)xminf;
            double xmax = (double)xmaxf;
            double ymin = (double)yminf;
            double ymax = (double)ymaxf;
            double step = (double)stepf;

            Vector <long>   vmax_iters = new Vector <long>(max_iters);
            Vector <double> vlimit     = new Vector <double>(limit);
            Vector <double> vinc       = new Vector <double>((double)Vector <double> .Count * step);
            Vector <double> vxmax      = new Vector <double>(xmax);
            Vector <double> vstep      = new Vector <double>(step);
            Vector <double> vxmin      = VectorHelper.Create(i => xmin + step * i);

            Parallel.For(0, (int)(((ymax - ymin) / step) + .5), (yp) =>
            {
                if (Abort)
                {
                    return;
                }

                Vector <double> vy = new Vector <double>(ymin + step * yp);
                int xp             = 0;
                for (Vector <double> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector <long> .Count)
                {
                    Vector <double> accumx = vx;
                    Vector <double> accumy = vy;

                    Vector <long> viters    = Vector <long> .Zero;
                    Vector <long> increment = Vector <long> .One;

                    do
                    {
                        Vector <double> naccumx = accumx * accumx - accumy * accumy;
                        Vector <double> naccumy = accumx * accumy + accumx * accumy;
                        accumx  = naccumx + vx;
                        accumy  = naccumy + vy;
                        viters += increment;
                        Vector <double> sqabs = accumx * accumx + accumy * accumy;
                        Vector <long> vCond   = Vector.LessThanOrEqual(sqabs, vlimit) &
                                                Vector.LessThanOrEqual(viters, vmax_iters);
                        increment = increment & vCond;
                    } while (increment != Vector <long> .Zero);

                    viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
                }
            });
        }
Пример #3
0
        // Render the fractal on a single thread using raw Vector<double> data types
        // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
        public void RenderSingleThreadedNoADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
        {
            double xmin = (double)xminf;
            double xmax = (double)xmaxf;
            double ymin = (double)yminf;
            double ymax = (double)ymaxf;
            double step = (double)stepf;

            Vector <double> vlimit     = new Vector <double>(limit);
            Vector <double> vinc       = new Vector <double>((double)Vector <double> .Count * step);
            Vector <double> vstep      = new Vector <double>(step);
            Vector <long>   vmax_iters = new Vector <long>(max_iters);
            Vector <double> vxmin      = VectorHelper.Create(i => xmin + step * i);

            double y  = ymin;
            int    yp = 0;

            for (Vector <double> vy = new Vector <double>(ymin); y <= ymax && !Abort; vy += vstep, y += step, yp++)
            {
                int             xp     = 0;
                Vector <double> vxmaxd = new Vector <double>(xmax);
                for (Vector <double> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmaxd); vx += vinc, xp += Vector <long> .Count)
                {
                    Vector <double> accumx = vx;
                    Vector <double> accumy = vy;

                    Vector <long> viters    = Vector <long> .Zero;
                    Vector <long> increment = Vector <long> .One;

                    do
                    {
                        Vector <double> naccumx = accumx * accumx - accumy * accumy;
                        Vector <double> naccumy = accumx * accumy + accumx * accumy;
                        accumx  = naccumx + vx;
                        accumy  = naccumy + vy;
                        viters += increment;
                        Vector <double> sqabs = accumx * accumx + accumy * accumy;
                        Vector <long>   vCond = Vector.LessThanOrEqual(sqabs, vlimit) &
                                                Vector.LessThanOrEqual(viters, vmax_iters);
                        increment = increment & vCond;
                    } while (increment != Vector <long> .Zero);

                    viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
                }
            }
        }
Пример #4
0
        // Render the fractal on multiple threads using the ComplexVecDouble data type
        // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
        public void RenderMultiThreadedWithADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
        {
            double xmin = (double)xminf;
            double xmax = (double)xmaxf;
            double ymin = (double)yminf;
            double ymax = (double)ymaxf;
            double step = (double)stepf;

            Vector <long>   vmax_iters = new Vector <long>(max_iters);
            Vector <double> vlimit     = new Vector <double>(limit);
            Vector <double> vinc       = new Vector <double>((double)Vector <double> .Length * step);
            Vector <double> vxmax      = new Vector <double>(xmax);
            Vector <double> vstep      = new Vector <double>(step);
            Vector <double> vxmin      = VectorHelper.Create(i => xmin + step * i);

            Parallel.For(0, (int)(((ymax - ymin) / step) + .5), (yp) =>
            {
                if (Abort)
                {
                    return;
                }

                Vector <double> vy = new Vector <double>(ymin + step * yp);
                int xp             = 0;
                for (Vector <double> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector <long> .Length)
                {
                    ComplexVecDouble num   = new ComplexVecDouble(vx, vy);
                    ComplexVecDouble accum = num;

                    Vector <long> viters    = Vector <long> .Zero;
                    Vector <long> increment = Vector <long> .One;

                    do
                    {
                        accum   = accum.square() + num;
                        viters += increment;
                        Vector <long> vCond = Vector.LessThanOrEqual(accum.sqabs(), vlimit) &
                                              Vector.LessThanOrEqual(viters, vmax_iters);
                        increment = increment & vCond;
                    } while (increment != Vector <long> .Zero);

                    viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
                }
            });
        }
Пример #5
0
        // Render the fractal on multiple threads using raw Vector<float> data types
        // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT
        public void RenderMultiThreadedNoADT(float xmin, float xmax, float ymin, float ymax, float step)
        {
            Vector <int>   vmax_iters = new Vector <int>(max_iters);
            Vector <float> vlimit     = new Vector <float>(limit);
            Vector <float> vstep      = new Vector <float>(step);
            Vector <float> vinc       = new Vector <float>((float)Vector <float> .Length * step);
            Vector <float> vxmax      = new Vector <float>(xmax);
            Vector <float> vxmin      = VectorHelper.Create(i => xmin + step * i);

            Parallel.For(0, (int)(((ymax - ymin) / step) + .5f), (yp) =>
            {
                if (Abort)
                {
                    return;
                }

                Vector <float> vy = new Vector <float>(ymin + step * yp);
                int xp            = 0;
                for (Vector <float> vx = vxmin; Vector.LessThanOrEqualAll(vx, vxmax); vx += vinc, xp += Vector <int> .Length)
                {
                    Vector <float> accumx = vx;
                    Vector <float> accumy = vy;

                    Vector <int> viters    = Vector <int> .Zero;
                    Vector <int> increment = Vector <int> .One;
                    do
                    {
                        Vector <float> naccumx = accumx * accumx - accumy * accumy;
                        Vector <float> XtimesY = accumx * accumy;
                        Vector <float> naccumy = XtimesY + XtimesY;
                        accumx  = naccumx + vx;
                        accumy  = naccumy + vy;
                        viters += increment;
                        Vector <float> sqabs = accumx * accumx + accumy * accumy;
                        Vector <int> vCond   = Vector.LessThanOrEqual(sqabs, vlimit) &
                                               Vector.LessThanOrEqual(viters, vmax_iters);
                        increment = increment & vCond;
                    } while (increment != Vector <int> .Zero);

                    viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
                }
            });
        }
Пример #6
0
        // Render the fractal on a single thread using the ComplexVecDouble data type
        // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT in VectorFloat.cs
        public void RenderSingleThreadedWithADT(float xminf, float xmaxf, float yminf, float ymaxf, float stepf)
        {
            double xmin = (double)xminf;
            double xmax = (double)xmaxf;
            double ymin = (double)yminf;
            double ymax = (double)ymaxf;
            double step = (double)stepf;

            Vector <double> vmax_iters = new Vector <double>((double)max_iters);
            Vector <double> vlimit     = new Vector <double>(limit);
            Vector <double> vstep      = new Vector <double>(step);
            Vector <double> vinc       = new Vector <double>((double)Vector <double> .Length * step);
            Vector <double> vxmax      = new Vector <double>(xmax);
            Vector <double> vxmin      = VectorHelper.Create(i => xmin + step * i);

            double y  = ymin;
            int    yp = 0;

            for (Vector <double> vy = new Vector <double>(ymin); y <= ymax && !Abort; vy += vstep, y += step, yp++)
            {
                int xp = 0;
                for (Vector <double> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector <double> .Length)
                {
                    ComplexVecDouble num   = new ComplexVecDouble(vx, vy);
                    ComplexVecDouble accum = num;

                    Vector <double> viters    = Vector <double> .Zero;
                    Vector <double> increment = Vector <double> .One;
                    do
                    {
                        accum   = accum.square() + num;
                        viters += increment;
                        Vector <double> vCond = Vector.LessThanOrEqual <double>(accum.sqabs(), vlimit) &
                                                Vector.LessThanOrEqual <double>(viters, vmax_iters);
                        increment = increment & vCond;
                    } while (increment != Vector <double> .Zero);

                    viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
                }
            }
        }
Пример #7
0
        // Render the fractal on a single thread using raw Vector<float> data types
        // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT
        public void RenderSingleThreadedNoADT(float xmin, float xmax, float ymin, float ymax, float step)
        {
            Vector <int>   vmax_iters = new Vector <int>(max_iters);
            Vector <float> vlimit     = new Vector <float>(limit);
            Vector <float> vstep      = new Vector <float>(step);
            Vector <float> vxmax      = new Vector <float>(xmax);
            Vector <float> vinc       = new Vector <float>((float)Vector <float> .Length * step);
            Vector <float> vxmin      = VectorHelper.Create(i => xmin + step * i);

            float y  = ymin;
            int   yp = 0;

            for (Vector <float> vy = new Vector <float>(ymin); y <= ymax && !Abort; vy += vstep, y += step, yp++)
            {
                int xp = 0;
                for (Vector <float> vx = vxmin; Vector.LessThanOrEqualAll(vx, vxmax); vx += vinc, xp += Vector <int> .Length)
                {
                    Vector <float> accumx = vx;
                    Vector <float> accumy = vy;

                    Vector <int> viters    = Vector <int> .Zero;
                    Vector <int> increment = Vector <int> .One;
                    do
                    {
                        Vector <float> naccumx = accumx * accumx - accumy * accumy;
                        Vector <float> naccumy = accumx * accumy + accumx * accumy;
                        accumx  = naccumx + vx;
                        accumy  = naccumy + vy;
                        viters += increment;
                        Vector <float> sqabs = accumx * accumx + accumy * accumy;
                        Vector <int>   vCond = Vector.LessThanOrEqual(sqabs, vlimit) &
                                               Vector.LessThanOrEqual(viters, vmax_iters);
                        increment = increment & vCond;
                    } while (increment != Vector <int> .Zero);

                    viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, (int)iter));
                }
            }
        }
Пример #8
0
        // Render the fractal on multiple threads using the ComplexFloatVec data type
        // For a well commented version, go see VectorFloatRenderer.RenderSingleThreadedWithADT
        public void RenderMultiThreadedWithADT(float xmin, float xmax, float ymin, float ymax, float step)
        {
            Vector <int>   vmax_iters = new Vector <int>(max_iters);
            Vector <float> vlimit     = new Vector <float>(limit);
            Vector <float> vstep      = new Vector <float>(step);
            Vector <float> vinc       = new Vector <float>((float)Vector <float> .Count * step);
            Vector <float> vxmax      = new Vector <float>(xmax);
            Vector <float> vxmin      = VectorHelper.Create(i => xmin + step * i);

            Parallel.For(0, (int)(((ymax - ymin) / step) + .5f), (yp) =>
            {
                if (Abort)
                {
                    return;
                }

                Vector <float> vy = new Vector <float>(ymin + step * yp);
                int xp            = 0;
                for (Vector <float> vx = vxmin; Vector.LessThanOrEqualAny(vx, vxmax); vx += vinc, xp += Vector <int> .Count)
                {
                    ComplexVecFloat num   = new ComplexVecFloat(vx, vy);
                    ComplexVecFloat accum = num;

                    Vector <int> viters    = Vector <int> .Zero;
                    Vector <int> increment = Vector <int> .One;
                    do
                    {
                        accum              = accum.square() + num;
                        viters            += increment;
                        Vector <int> vCond = Vector.LessThanOrEqual(accum.sqabs(), vlimit) &
                                             Vector.LessThanOrEqual(viters, vmax_iters);
                        increment = increment & vCond;
                    } while (increment != Vector <int> .Zero);

                    viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, iter));
                }
            });
        }
Пример #9
0
        // Render the fractal on a single thread using the ComplexFloatVec data type
        // This is the implementation that has the best comments.
        public void RenderSingleThreadedWithADT(float xmin, float xmax, float ymin, float ymax, float step)
        {
            // Initialize a pile of method constant vectors
            Vector <int>   vmax_iters = new Vector <int>(max_iters);
            Vector <float> vlimit     = new Vector <float>(limit);
            Vector <float> vstep      = new Vector <float>(step);
            Vector <float> vxmax      = new Vector <float>(xmax);
            Vector <float> vinc       = new Vector <float>((float)Vector <float> .Count * step);
            // Use my little helper routine: it's kind of slow, but I find it pleasantly readable.
            // The alternative would be this:
            //    float[] xmins = new float[Vector<float>.Count];
            //    for (int i = 0; i < xmins.Count; i++)
            //        xmins[i] = xmin + step * i;
            //    Vector<float> vxmin = new Vector<float>(xmins);
            // Both allocate some memory, this one just does it in a separate routine :-)
            Vector <float> vxmin = VectorHelper.Create(i => xmin + step * i);

            float y  = ymin;
            int   yp = 0;

            for (Vector <float> vy = new Vector <float>(ymin);
                 y <= ymax && !Abort;
                 vy += vstep, y += step, yp++)
            {
                int xp = 0;
                for (Vector <float> vx = vxmin;
                     Vector.LessThanOrEqualAny(vx, vxmax); // Vector.{comparision}Any|All return bools, not masks
                     vx += vinc, xp += Vector <int> .Count)
                {
                    ComplexVecFloat num   = new ComplexVecFloat(vx, vy);
                    ComplexVecFloat accum = num;

                    Vector <int> viters    = Vector <int> .Zero; // Iteration counts start at all zeros
                    Vector <int> increment = Vector <int> .One;  // Increment starts out as all ones
                    do
                    {
                        // This is work that can be vectorized
                        accum = accum.square() + num;
                        // Increment the iteration count Only pixels that haven't already hit the
                        // limit will be incremented because the increment variable gets masked below
                        viters += increment;
                        // Create a mask that correspons to the element-wise logical operation
                        // "accum <= limit && iters <= max_iters" Note that the bitwise and is used,
                        // because the Vector.{comparision} operations return masks, not boolean values
                        Vector <int> vCond = Vector.LessThanOrEqual(accum.sqabs(), vlimit) &
                                             Vector.LessThanOrEqual(viters, vmax_iters);
                        // increment becomes zero for the elems that have hit the limit because
                        // vCond is a mask of all zeros or ones, based on the results of the
                        // Vector.{comparison} operations
                        increment = increment & vCond;
                        // Keep going until we have no elements that haven't either hit the value
                        // limit or the iteration count
                    } while (increment != Vector <int> .Zero);

                    // This is another little helper I created. It's definitely kind of slow but I
                    // find it pleasantly succinct. It could also be written like this:
                    //
                    // for (int eNum = 0; eNum < Vector<int>.Count; eNum++)
                    //     DrawPixel(xp + eNum, yp, viters[eNum]);
                    //
                    // Neither implementation is particularly fast, because pulling individual elements
                    // is a slow operation for vector types.
                    viters.ForEach((iter, elemNum) => DrawPixel(xp + elemNum, yp, iter));
                }
            }
        }