private void DivideAndConquer(ArrayList groupBucket, double[] gaps, double threshold, int a, int b)
    {
        // First, check for trivial recursion
        // (for example, if there's only one element in range).
        if (a == b)
        {
            // Add group (of one) to bucket, and pop back up the stack.
            IndexValueCouplet[] group = new IndexValueCouplet[1];
            Array.Copy(this.svalues, a, group, 0, 1);

            groupBucket.Add(group);
            return;
        }

        // Find the two biggest gaps (or biggest single gap, if there's only
        // two points in this range).
        System.Diagnostics.Debug.Assert(gaps.Length > 0);
        int biggest = -1; int biggest2 = -1;

        for (int i = a; i < b; ++i)
        {
            if (biggest < 0 || gaps[i] > gaps[biggest])
            {
                biggest2 = biggest; biggest = i;
            }
            else if (biggest2 < 0 || gaps[i] > gaps[biggest2])
            {
                biggest2 = i;
            }
        }
        if (biggest2 < 0)
        {
            biggest2 = biggest;
        }

        // Only split further if one of the following two conditions is met:
        //   - range > 2x specified threshold, or
        //   - range > 1x threshold, and there exists an obvious split point
        //     (say, a gap 1.5x bigger than any other).
        double range        = svalues[b].value - svalues[a].value;
        double gapSizeRatio = gaps[biggest] / gaps[biggest2];

        if ((range > 2 * threshold) || (range > 1 * threshold && gapSizeRatio > 1.5))
        {
            // Split on the biggest single gap.
            DivideAndConquer(groupBucket, gaps, threshold, a, biggest);
            DivideAndConquer(groupBucket, gaps, threshold, biggest + 1, b);
        }
        else
        {
            // Add group to bucket, and pop back up the stack.
            int n = b - a + 1;
            IndexValueCouplet[] group = new IndexValueCouplet[n];
            Array.Copy(this.svalues, a, group, 0, n);

            groupBucket.Add(group);
            return;
        }
    }
    public ScalarPartitioning(double[] values)
    {
        int n = values.Length;

        // Plot the values on a number line (in other words, sort them).
        // But retain the ordering of the items, for later re-ordering.
        this.svalues = new IndexValueCouplet[n];
        for (int i=0; i < n; ++i)
            svalues[i] = new IndexValueCouplet(i,values[i]);

        Array.Sort(svalues,IndexValueCouplet.ByValue);
    }
            public int Compare(object x, object y)
            {
                IndexValueCouplet xx = (IndexValueCouplet)x;
                IndexValueCouplet yy = (IndexValueCouplet)y;

                if (xx.value == yy.value)
                {
                    return(0);
                }
                else
                {
                    return((xx.value < yy.value) ? -1 : +1);
                }
            }
    public ScalarPartitioning(double[] values)
    {
        int n = values.Length;

        // Plot the values on a number line (in other words, sort them).
        // But retain the ordering of the items, for later re-ordering.
        this.svalues = new IndexValueCouplet[n];
        for (int i = 0; i < n; ++i)
        {
            svalues[i] = new IndexValueCouplet(i, values[i]);
        }

        Array.Sort(svalues, IndexValueCouplet.ByValue);
    }
    private void DivideAndConquer(ArrayList groupBucket, double[] gaps, double threshold, int a, int b)
    {
        // First, check for trivial recursion
        // (for example, if there's only one element in range).
        if (a == b)
        {
            // Add group (of one) to bucket, and pop back up the stack.
            IndexValueCouplet[] group = new IndexValueCouplet[1];
            Array.Copy(this.svalues,a,group,0,1);

            groupBucket.Add(group);
            return;
        }

        // Find the two biggest gaps (or biggest single gap, if there's only
        // two points in this range).
        System.Diagnostics.Debug.Assert(gaps.Length > 0);
        int biggest = -1; int biggest2 = -1;
        for (int i=a; i < b; ++i)
        {
            if (biggest < 0 || gaps[i] > gaps[biggest])
            {
                biggest2 = biggest; biggest = i;
            }
            else if (biggest2 < 0 || gaps[i] > gaps[biggest2])
            {
                biggest2 = i;
            }
        }
        if (biggest2 < 0) biggest2 = biggest;

        // Only split further if one of the following two conditions is met:
        //   - range > 2x specified threshold, or
        //   - range > 1x threshold, and there exists an obvious split point
        //     (say, a gap 1.5x bigger than any other).
        double range = svalues[b].value-svalues[a].value;
        double gapSizeRatio = gaps[biggest]/gaps[biggest2];
        if ((range > 2*threshold) || (range > 1*threshold && gapSizeRatio > 1.5))
        {
            // Split on the biggest single gap.
            DivideAndConquer(groupBucket, gaps, threshold, a, biggest);
            DivideAndConquer(groupBucket, gaps, threshold, biggest+1, b);
        }
        else
        {
            // Add group to bucket, and pop back up the stack.
            int n = b-a+1;
            IndexValueCouplet[] group = new IndexValueCouplet[n];
            Array.Copy(this.svalues,a,group,0,n);

            groupBucket.Add(group);
            return;
        }
    }