/// <summary>
 /// Initializes the.
 /// </summary>
 /// <param name="args">The args.</param>
 public override void Initialize(params object[] args)
 {
     if (Buffer != null)
     {
         Buffer.Dispose();
     }
     base.Initialize(args);
     Buffer = HardwareAcceleratorManager.GPUAccelerator.Allocate <byte>((int)args[0], (int)args[1]);
     Buffer.MemSetToZero();
     RequireCopyTo = true;
 }
        public static void Execute(int[,] clusters)
        {
            using (MemoryBuffer2D <int> clusterBuff = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(clusters.GetLength(0), clusters.GetLength(1)))
            {
                clusterBuff.CopyFrom(clusters, Index2.Zero, Index2.Zero, clusterBuff.Extent);
                using (MemoryBuffer3D <int> diffs = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(clusterBuff.Extent.X, clusterBuff.Extent.X, 5))
                    using (MemoryBuffer2D <int> bests = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(clusterBuff.Extent.X, 3 + clusterBuff.Extent.X))
                    {
                        bool change = true;
                        while (change)
                        {
                            change = false;
                            diffs.MemSetToZero();
                            bests.MemSetToZero();
                            kernel(new Index2(clusterBuff.Extent.X, clusterBuff.Extent.X), clusterBuff, diffs);
                            HardwareAcceleratorManager.GPUAccelerator.Synchronize();
                            kernelBests(bests.Extent.X, diffs, bests);
                            HardwareAcceleratorManager.GPUAccelerator.Synchronize();

                            int[,] best = new int[bests.Extent.X, bests.Extent.Y];
                            bests.CopyTo(best, Index2.Zero, Index2.Zero, bests.Extent);

                            int eq    = -1;
                            int diffl = -1;
                            int ts    = -1;
                            for (int i = 0; i < best.GetLength(0); i++)
                            {
                                if (best[i, 0] > eq)
                                {
                                    eq    = best[i, 0];
                                    diffl = best[i, 1];
                                    ts    = best[i, 2];
                                }
                                else if (best[i, 0] == eq && best[i, 1] > diffl)
                                {
                                    diffl = best[i, 1];
                                    ts    = best[i, 2];
                                }
                                else if (best[i, 0] == eq && best[i, 1] == diffl && ts < best[i, 2])
                                {
                                    ts = best[i, 2];
                                }
                            }

                            if (eq >= 0)
                            {
                                change = true;

                                List <int> bestofbest   = new List <int>();
                                List <int> bestofbestID = new List <int>();

                                for (int i = 0; i < best.GetLength(0); i++)
                                {
                                    if (eq == best[i, 0] && diffl == best[i, 1] && ts == best[i, 2])
                                    {
                                        for (int j = 3; j < best.GetLength(1); j++)
                                        {
                                            if (best[i, j] < 0)
                                            {
                                                break;
                                            }
                                            else
                                            {
                                                bestofbest.Add(i);
                                                bestofbestID.Add(best[i, j]);
                                            }
                                        }
                                    }
                                }

                                int[] bob1 = bestofbest.ToArray();
                                int[] bob2 = bestofbestID.ToArray();
                                int[] bob3 = new int[bob1.Length];
                                bool  repeated;

                                for (int i = 0, k = 0; i < bob1.Length; i++)
                                {
                                    bob3[i]  = bob1[i];
                                    repeated = false;
                                    for (int j = 0; j < i; j++)
                                    {
                                        if (bob3[i] == bob3[j])
                                        {
                                            repeated = true;
                                        }
                                    }
                                    if (repeated)
                                    {
                                        for (int j = k; j < bob2.Length; j++)
                                        {
                                            repeated = false;
                                            for (int q = 0; q < i; q++)
                                            {
                                                if (bob3[q] == bob2[j])
                                                {
                                                    repeated = true;
                                                    break;
                                                }
                                            }
                                            if (!repeated)
                                            {
                                                bob3[i] = bob2[j];
                                                k       = j;
                                                break;
                                            }
                                        }
                                    }
                                }

                                using (MemoryBuffer <int> bobbuff1 = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(bestofbest.Count))
                                    using (MemoryBuffer <int> bobbuff2 = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(bestofbestID.Count))
                                        using (MemoryBuffer <int> newPos = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(bestofbest.Count))
                                            using (MemoryBuffer2D <int> newPals = HardwareAcceleratorManager.GPUAccelerator.Allocate <int>(bestofbestID.Count, clusterBuff.Extent.Y))
                                            {
                                                newPals.MemSetToZero();
                                                bobbuff1.CopyFrom(bob1, 0, 0, bobbuff1.Extent);
                                                bobbuff2.CopyFrom(bob2, 0, 0, bobbuff2.Extent);
                                                newPos.CopyFrom(bob3, 0, 0, newPos.Extent);
                                                kernelInvalidateCluster(bobbuff1.Extent, bobbuff1, bobbuff2, newPals, clusterBuff);
                                                HardwareAcceleratorManager.GPUAccelerator.Synchronize();
                                                kernelCopyNewPal(newPos.Extent, newPos, newPals, clusterBuff);
                                                HardwareAcceleratorManager.GPUAccelerator.Synchronize();
                                                kernelFilter(bobbuff1.Extent, bobbuff1, newPos, clusterBuff);
                                                HardwareAcceleratorManager.GPUAccelerator.Synchronize();
                                                kernelFilter(bobbuff2.Extent, bobbuff2, newPos, clusterBuff);
                                                HardwareAcceleratorManager.GPUAccelerator.Synchronize();
                                            }
                                kernelRemoveRepeated(new Index2(clusterBuff.Extent.X, clusterBuff.Extent.X), clusterBuff);
                                HardwareAcceleratorManager.GPUAccelerator.Synchronize();
                            }
                        }
                    }
                clusterBuff.CopyTo(clusters, Index2.Zero, Index2.Zero, clusterBuff.Extent);
            }
        }