/// <summary>Executes sort on the Bucket_sort.</summary>
        /// <remarks>
        /// Executes sort on the Bucket_sort. The result is fed into the indices
        /// array in the range between begin (inclusive) and end (exclusive). Uses
        /// user supplied sorter to execute sort on each bucket. Users either supply
        /// the sorter and use this method of Bucket_sort class, or use other methods
        /// to form the buckets and take care of bucket sorting themselves.
        /// </remarks>
        public void Sort(com.epl.geometry.AttributeStreamOfInt32 indices, int begin, int end, com.epl.geometry.ClassicSort sorter)
        {
            if (end - begin < 32)
            {
                sorter.UserSort(begin, end, indices);
                return;
            }
            bool b_fallback = true;

            try
            {
                double miny = com.epl.geometry.NumberUtils.PositiveInf();
                double maxy = com.epl.geometry.NumberUtils.NegativeInf();
                for (int i = begin; i < end; i++)
                {
                    double y = sorter.GetValue(indices.Get(i));
                    if (y < miny)
                    {
                        miny = y;
                    }
                    if (y > maxy)
                    {
                        maxy = y;
                    }
                }
                if (Reset(end - begin, miny, maxy, end - begin))
                {
                    for (int i_1 = begin; i_1 < end; i_1++)
                    {
                        int    vertex = indices.Get(i_1);
                        double y      = sorter.GetValue(vertex);
                        int    bucket = GetBucket(y);
                        m_buckets.Set(bucket, m_buckets.Get(bucket) + 1);
                        // counting
                        // values
                        // in a
                        // bucket.
                        m_bucketed_indices.Write(i_1 - begin, vertex);
                    }
                    // Recalculate buckets to contain start positions of buckets.
                    int c = m_buckets.Get(0);
                    m_buckets.Set(0, 0);
                    for (int i_2 = 1, n = m_buckets.Size(); i_2 < n; i_2++)
                    {
                        int b = m_buckets.Get(i_2);
                        m_buckets.Set(i_2, c);
                        c += b;
                    }
                    for (int i_3 = begin; i_3 < end; i_3++)
                    {
                        int    vertex       = m_bucketed_indices.Read(i_3 - begin);
                        double y            = sorter.GetValue(vertex);
                        int    bucket       = GetBucket(y);
                        int    bucket_index = m_buckets.Get(bucket);
                        indices.Set(bucket_index + begin, vertex);
                        m_buckets.Set(bucket, bucket_index + 1);
                    }
                    b_fallback = false;
                }
            }
            catch (System.Exception)
            {
                m_buckets.Resize(0);
                m_bucketed_indices.Resize(0);
            }
            if (b_fallback)
            {
                sorter.UserSort(begin, end, indices);
                return;
            }
            int j = 0;

            for (int i_4 = 0, n = m_buckets.Size(); i_4 < n; i_4++)
            {
                int j0 = j;
                j = m_buckets.Get(i_4);
                if (j > j0)
                {
                    sorter.UserSort(begin + j0, begin + j, indices);
                }
            }
            System.Diagnostics.Debug.Assert((j == end));
            if (GetBucketCount() > 100)
            {
                // some heuristics to preserve memory
                m_buckets.Resize(0);
                m_bucketed_indices.Resize(0);
            }
        }