U0 QuickSortI64(I64 *base, I64 num, I64 (*fp_compare)(I64 e1, I64 e2))
{/*Quick Sort for width==8.
fp_compare() passes by value instead of ref.

For ascending strings: return StrCompare(e1,e2);
For ascending ints       : return e1-e2;

Maybe, look at ::/Demo/MultiCore/MPRadix.CC.
*/
        I64 i, *left, *right, pivot;

        if (num > 1)
        {
                left  = base;
                right = base + num - 1;
                pivot = base[num / 2];
                do
                {
                        while ((*fp_compare)(*left, pivot) < 0)
                                left++;
                        while ((*fp_compare)(*right, pivot) > 0)
                                right--;
                        if (left <= right)
                                SwapI64(left++, right--);
                }
                while (left <= right);

                i = right + 1 - base;
                if (1 < i < num)
                        QuickSortI64(base, i, fp_compare);
                i = base + num - left;
                if (1 < i < num)
                        QuickSortI64(left, i, fp_compare);
        }
}

U0 QuickSort2a(U8 **base, I64 num, I64 (*fp_compare)(U8 **_e1, U8 **_e2))
{//Not public.For case of width==size(U8 *)==8.
//fp_compare() passes by ref.
        I64  i;
        U8 **left, **right, *pivot;

        left  = base;
        right = base + num - 1;
        pivot = base[num / 2];
        do
        {
                while ((*fp_compare)(left, &pivot) < 0)
                        left++;
                while ((*fp_compare)(right, &pivot) > 0)
                        right--;
                if (left <= right)
                        SwapI64(left++, right--);
        }
        while (left <= right);

        i = right + 1 - base;
        if (1 < i < num)
                QuickSort2a(base, i, fp_compare);
        i = base + num - left;
        if (1 < i < num)
                QuickSort2a(left, i, fp_compare);
}
U0 QuickSort2b(U8 *base, I64 num, I64 width, I64 (*fp_compare)(U8 *e1, U8 *e2), U8 *tmp)
{//Not public
        I64 i;
        U8 *left, *right, *pivot = tmp + width;

        left  = base;
        right = base + (num - 1) * width;
        MemCopy(pivot, base + num / 2 * width, width);
        do
        {
                while ((*fp_compare)(left, pivot) < 0)
                        left += width;
                while ((*fp_compare)(right, pivot) > 0)
                        right -= width;
                if (left <= right)
                {
                        if (left != right)
                        {
                                MemCopy(tmp, right, width);
                                MemCopy(right, left, width);
                                MemCopy(left, tmp, width);
                        }
                        left  += width;
                        right -= width;
                }
        }
        while (left <= right);

        i = 1 + (right - base) / width;
        if (1 < i < num)
                QuickSort2b(base, i, width, fp_compare, tmp);
        i = num + (base - left) / width;
        if (1 < i < num)
                QuickSort2b(left, i, width, fp_compare, tmp);
}
U0 QuickSort(U8 *base, I64 num, I64 width, I64 (*fp_compare)(U8 *e1, U8 *e2))
{/*Quick Sort: fp_compare() passes by ref.

For ascending strings: return StrCompare(*e1,*e2);
For ascending ints       : return *e1-*e2;
Don't return e1-e2 if numbers can overflow, return -1,0 or 1.

Maybe, look at ::/Demo/MultiCore/MPRadix.CC.
*/
        U8 *tmp;

        if (width && num > 1)
        {
                if (width == sizeof(U8 *))              //assign instead of MemCopy for width 8
                        QuickSort2a(base, num, fp_compare);
                else
                {
                        tmp = MAlloc(width * 2);
                        QuickSort2b(base, num, width, fp_compare, tmp);
                        Free(tmp);
                }
        }
}