#line 1 "numpy/core/src/npysort/heapsort.c.src"

/*
 *****************************************************************************
 **       This file was autogenerated from a template  DO NOT EDIT!!!!      **
 **       Changes should be made to the original source (.src) file         **
 *****************************************************************************
 */

#line 1
/* -*- c -*- */

/*
 * The purpose of this module is to add faster sort functions
 * that are type-specific.  This is done by altering the
 * function table for the builtin descriptors.
 *
 * These sorting functions are copied almost directly from numarray
 * with a few modifications (complex comparisons compare the imaginary
 * part if the real parts are equal, for example), and the names
 * are changed.
 *
 * The original sorting code is due to Charles R. Harris who wrote
 * it for numarray.
 */

/*
 * Quick sort is usually the fastest, but the worst case scenario can
 * be slower than the merge and heap sorts.  The merge sort requires
 * extra memory and so for large arrays may not be useful.
 *
 * The merge sort is *stable*, meaning that equal components
 * are unmoved from their entry versions, so it can be used to
 * implement lexigraphic sorting on multiple keys.
 *
 * The heap sort is included for completeness.
 */

#define NPY_NO_DEPRECATED_API NPY_API_VERSION

#include "npy_sort.h"
#include "npysort_common.h"
#include <stdlib.h>

#define NOT_USED NPY_UNUSED(unused)
#define PYA_QS_STACK 100
#define SMALL_QUICKSORT 15
#define SMALL_MERGESORT 20
#define SMALL_STRING 16


/*
 *****************************************************************************
 **                            NUMERIC SORTS                                **
 *****************************************************************************
 */


#line 62

NPY_NO_EXPORT int
heapsort_bool(void *start, npy_intp n, void *NOT_USED)
{
    npy_bool tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_bool *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && BOOL_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (BOOL_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && BOOL_LT(a[j], a[j+1])) {
                j++;
            }
            if (BOOL_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_bool(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_bool *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && BOOL_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (BOOL_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && BOOL_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (BOOL_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_byte(void *start, npy_intp n, void *NOT_USED)
{
    npy_byte tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_byte *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && BYTE_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (BYTE_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && BYTE_LT(a[j], a[j+1])) {
                j++;
            }
            if (BYTE_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_byte(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_byte *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && BYTE_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (BYTE_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && BYTE_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (BYTE_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_ubyte(void *start, npy_intp n, void *NOT_USED)
{
    npy_ubyte tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_ubyte *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && UBYTE_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (UBYTE_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && UBYTE_LT(a[j], a[j+1])) {
                j++;
            }
            if (UBYTE_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_ubyte(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_ubyte *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && UBYTE_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (UBYTE_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && UBYTE_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (UBYTE_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_short(void *start, npy_intp n, void *NOT_USED)
{
    npy_short tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_short *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && SHORT_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (SHORT_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && SHORT_LT(a[j], a[j+1])) {
                j++;
            }
            if (SHORT_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_short(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_short *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && SHORT_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (SHORT_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && SHORT_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (SHORT_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_ushort(void *start, npy_intp n, void *NOT_USED)
{
    npy_ushort tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_ushort *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && USHORT_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (USHORT_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && USHORT_LT(a[j], a[j+1])) {
                j++;
            }
            if (USHORT_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_ushort(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_ushort *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && USHORT_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (USHORT_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && USHORT_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (USHORT_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_int(void *start, npy_intp n, void *NOT_USED)
{
    npy_int tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_int *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && INT_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (INT_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && INT_LT(a[j], a[j+1])) {
                j++;
            }
            if (INT_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_int(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_int *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && INT_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (INT_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && INT_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (INT_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_uint(void *start, npy_intp n, void *NOT_USED)
{
    npy_uint tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_uint *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && UINT_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (UINT_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && UINT_LT(a[j], a[j+1])) {
                j++;
            }
            if (UINT_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_uint(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_uint *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && UINT_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (UINT_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && UINT_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (UINT_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_long(void *start, npy_intp n, void *NOT_USED)
{
    npy_long tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_long *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && LONG_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (LONG_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && LONG_LT(a[j], a[j+1])) {
                j++;
            }
            if (LONG_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_long(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_long *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && LONG_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (LONG_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && LONG_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (LONG_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_ulong(void *start, npy_intp n, void *NOT_USED)
{
    npy_ulong tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_ulong *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && ULONG_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (ULONG_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && ULONG_LT(a[j], a[j+1])) {
                j++;
            }
            if (ULONG_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_ulong(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_ulong *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && ULONG_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (ULONG_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && ULONG_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (ULONG_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_longlong(void *start, npy_intp n, void *NOT_USED)
{
    npy_longlong tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_longlong *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && LONGLONG_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (LONGLONG_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && LONGLONG_LT(a[j], a[j+1])) {
                j++;
            }
            if (LONGLONG_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_longlong(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_longlong *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && LONGLONG_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (LONGLONG_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && LONGLONG_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (LONGLONG_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_ulonglong(void *start, npy_intp n, void *NOT_USED)
{
    npy_ulonglong tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_ulonglong *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && ULONGLONG_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (ULONGLONG_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && ULONGLONG_LT(a[j], a[j+1])) {
                j++;
            }
            if (ULONGLONG_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_ulonglong(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_ulonglong *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && ULONGLONG_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (ULONGLONG_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && ULONGLONG_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (ULONGLONG_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_half(void *start, npy_intp n, void *NOT_USED)
{
    npy_ushort tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_ushort *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && HALF_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (HALF_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && HALF_LT(a[j], a[j+1])) {
                j++;
            }
            if (HALF_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_half(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_ushort *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && HALF_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (HALF_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && HALF_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (HALF_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_float(void *start, npy_intp n, void *NOT_USED)
{
    npy_float tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_float *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && FLOAT_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (FLOAT_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && FLOAT_LT(a[j], a[j+1])) {
                j++;
            }
            if (FLOAT_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_float(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_float *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && FLOAT_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (FLOAT_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && FLOAT_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (FLOAT_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_double(void *start, npy_intp n, void *NOT_USED)
{
    npy_double tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_double *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && DOUBLE_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (DOUBLE_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && DOUBLE_LT(a[j], a[j+1])) {
                j++;
            }
            if (DOUBLE_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_double(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_double *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && DOUBLE_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (DOUBLE_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && DOUBLE_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (DOUBLE_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_longdouble(void *start, npy_intp n, void *NOT_USED)
{
    npy_longdouble tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_longdouble *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && LONGDOUBLE_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (LONGDOUBLE_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && LONGDOUBLE_LT(a[j], a[j+1])) {
                j++;
            }
            if (LONGDOUBLE_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_longdouble(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_longdouble *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && LONGDOUBLE_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (LONGDOUBLE_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && LONGDOUBLE_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (LONGDOUBLE_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_cfloat(void *start, npy_intp n, void *NOT_USED)
{
    npy_cfloat tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_cfloat *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && CFLOAT_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (CFLOAT_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && CFLOAT_LT(a[j], a[j+1])) {
                j++;
            }
            if (CFLOAT_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_cfloat(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_cfloat *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && CFLOAT_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (CFLOAT_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && CFLOAT_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (CFLOAT_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_cdouble(void *start, npy_intp n, void *NOT_USED)
{
    npy_cdouble tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_cdouble *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && CDOUBLE_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (CDOUBLE_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && CDOUBLE_LT(a[j], a[j+1])) {
                j++;
            }
            if (CDOUBLE_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_cdouble(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_cdouble *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && CDOUBLE_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (CDOUBLE_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && CDOUBLE_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (CDOUBLE_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_clongdouble(void *start, npy_intp n, void *NOT_USED)
{
    npy_clongdouble tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_clongdouble *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && CLONGDOUBLE_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (CLONGDOUBLE_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && CLONGDOUBLE_LT(a[j], a[j+1])) {
                j++;
            }
            if (CLONGDOUBLE_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_clongdouble(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_clongdouble *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && CLONGDOUBLE_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (CLONGDOUBLE_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && CLONGDOUBLE_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (CLONGDOUBLE_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_datetime(void *start, npy_intp n, void *NOT_USED)
{
    npy_datetime tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_datetime *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && DATETIME_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (DATETIME_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && DATETIME_LT(a[j], a[j+1])) {
                j++;
            }
            if (DATETIME_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_datetime(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_datetime *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && DATETIME_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (DATETIME_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && DATETIME_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (DATETIME_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 62

NPY_NO_EXPORT int
heapsort_timedelta(void *start, npy_intp n, void *NOT_USED)
{
    npy_timedelta tmp, *a;
    npy_intp i,j,l;

    /* The array needs to be offset by one for heapsort indexing */
    a = (npy_timedelta *)start - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && TIMEDELTA_LT(a[j], a[j+1])) {
                j += 1;
            }
            if (TIMEDELTA_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && TIMEDELTA_LT(a[j], a[j+1])) {
                j++;
            }
            if (TIMEDELTA_LT(tmp, a[j])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


NPY_NO_EXPORT int
aheapsort_timedelta(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED)
{
    npy_timedelta *v = vv;
    npy_intp *a, i,j,l, tmp;
    /* The arrays need to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && TIMEDELTA_LT(v[a[j]], v[a[j+1]])) {
                j += 1;
            }
            if (TIMEDELTA_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && TIMEDELTA_LT(v[a[j]], v[a[j+1]])) {
                j++;
            }
            if (TIMEDELTA_LT(v[tmp], v[a[j]])) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}




/*
 *****************************************************************************
 **                             STRING SORTS                                **
 *****************************************************************************
 */


#line 179

NPY_NO_EXPORT int
heapsort_string(void *start, npy_intp n, void *varr)
{
    PyArrayObject *arr = varr;
    size_t len = PyArray_ITEMSIZE(arr)/sizeof(npy_char);
    npy_char *tmp = malloc(PyArray_ITEMSIZE(arr));
    npy_char *a = (npy_char *)start - len;
    npy_intp i, j, l;

    if (tmp == NULL) {
        return -NPY_ENOMEM;
    }

    for (l = n>>1; l > 0; --l) {
        STRING_COPY(tmp, a + l*len, len);
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && STRING_LT(a + j*len, a + (j+1)*len, len))
                j += 1;
            if (STRING_LT(tmp, a + j*len, len)) {
                STRING_COPY(a + i*len, a + j*len, len);
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        STRING_COPY(a + i*len, tmp, len);
    }

    for (; n > 1;) {
        STRING_COPY(tmp, a + n*len, len);
        STRING_COPY(a + n*len, a + len, len);
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && STRING_LT(a + j*len, a + (j+1)*len, len))
                j++;
            if (STRING_LT(tmp, a + j*len, len)) {
                STRING_COPY(a + i*len, a + j*len, len);
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        STRING_COPY(a + i*len, tmp, len);
    }

    free(tmp);
    return 0;
}


NPY_NO_EXPORT int
aheapsort_string(void *vv, npy_intp *tosort, npy_intp n, void *varr)
{
    npy_char *v = vv;
    PyArrayObject *arr = varr;
    size_t len = PyArray_ITEMSIZE(arr)/sizeof(npy_char);
    npy_intp *a, i,j,l, tmp;

    /* The array needs to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && STRING_LT(v + a[j]*len, v + a[j+1]*len, len))
                j += 1;
            if (STRING_LT(v + tmp*len, v + a[j]*len, len)) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && STRING_LT(v + a[j]*len, v + a[j+1]*len, len))
                j++;
            if (STRING_LT(v + tmp*len, v + a[j]*len, len)) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}


#line 179

NPY_NO_EXPORT int
heapsort_unicode(void *start, npy_intp n, void *varr)
{
    PyArrayObject *arr = varr;
    size_t len = PyArray_ITEMSIZE(arr)/sizeof(npy_ucs4);
    npy_ucs4 *tmp = malloc(PyArray_ITEMSIZE(arr));
    npy_ucs4 *a = (npy_ucs4 *)start - len;
    npy_intp i, j, l;

    if (tmp == NULL) {
        return -NPY_ENOMEM;
    }

    for (l = n>>1; l > 0; --l) {
        UNICODE_COPY(tmp, a + l*len, len);
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && UNICODE_LT(a + j*len, a + (j+1)*len, len))
                j += 1;
            if (UNICODE_LT(tmp, a + j*len, len)) {
                UNICODE_COPY(a + i*len, a + j*len, len);
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        UNICODE_COPY(a + i*len, tmp, len);
    }

    for (; n > 1;) {
        UNICODE_COPY(tmp, a + n*len, len);
        UNICODE_COPY(a + n*len, a + len, len);
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && UNICODE_LT(a + j*len, a + (j+1)*len, len))
                j++;
            if (UNICODE_LT(tmp, a + j*len, len)) {
                UNICODE_COPY(a + i*len, a + j*len, len);
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        UNICODE_COPY(a + i*len, tmp, len);
    }

    free(tmp);
    return 0;
}


NPY_NO_EXPORT int
aheapsort_unicode(void *vv, npy_intp *tosort, npy_intp n, void *varr)
{
    npy_ucs4 *v = vv;
    PyArrayObject *arr = varr;
    size_t len = PyArray_ITEMSIZE(arr)/sizeof(npy_ucs4);
    npy_intp *a, i,j,l, tmp;

    /* The array needs to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n>>1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && UNICODE_LT(v + a[j]*len, v + a[j+1]*len, len))
                j += 1;
            if (UNICODE_LT(v + tmp*len, v + a[j]*len, len)) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && UNICODE_LT(v + a[j]*len, v + a[j+1]*len, len))
                j++;
            if (UNICODE_LT(v + tmp*len, v + a[j]*len, len)) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}




/*
 *****************************************************************************
 **                             GENERIC SORT                                **
 *****************************************************************************
 */


NPY_NO_EXPORT int
npy_heapsort(void *start, npy_intp num, void *varr)
{
    PyArrayObject *arr = varr;
    npy_intp elsize = PyArray_ITEMSIZE(arr);
    PyArray_CompareFunc *cmp = PyArray_DESCR(arr)->f->compare;
    char *tmp = malloc(elsize);
    char *a = (char *)start - elsize;
    npy_intp i, j, l;

    if (tmp == NULL) {
        return -NPY_ENOMEM;
    }

    for (l = num >> 1; l > 0; --l) {
        GENERIC_COPY(tmp, a + l*elsize, elsize);
        for (i = l, j = l << 1; j <= num;) {
            if (j < num && cmp(a + j*elsize, a + (j+1)*elsize, arr) < 0) {
                ++j;
            }
            if (cmp(tmp, a + j*elsize, arr) < 0) {
                GENERIC_COPY(a + i*elsize, a + j*elsize, elsize);
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        GENERIC_COPY(a + i*elsize, tmp, elsize);
    }

    for (; num > 1;) {
        GENERIC_COPY(tmp, a + num*elsize, elsize);
        GENERIC_COPY(a + num*elsize, a + elsize, elsize);
        num -= 1;
        for (i = 1, j = 2; j <= num;) {
            if (j < num && cmp(a + j*elsize, a + (j+1)*elsize, arr) < 0) {
                ++j;
            }
            if (cmp(tmp, a + j*elsize, arr) < 0) {
                GENERIC_COPY(a + i*elsize, a + j*elsize, elsize);
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        GENERIC_COPY(a + i*elsize, tmp, elsize);
    }

    free(tmp);
    return 0;
}


NPY_NO_EXPORT int
npy_aheapsort(void *vv, npy_intp *tosort, npy_intp n, void *varr)
{
    char *v = vv;
    PyArrayObject *arr = varr;
    npy_intp elsize = PyArray_ITEMSIZE(arr);
    PyArray_CompareFunc *cmp = PyArray_DESCR(arr)->f->compare;
    npy_intp *a, i, j, l, tmp;

    /* The array needs to be offset by one for heapsort indexing */
    a = tosort - 1;

    for (l = n >> 1; l > 0; --l) {
        tmp = a[l];
        for (i = l, j = l<<1; j <= n;) {
            if (j < n && cmp(v + a[j]*elsize, v + a[j+1]*elsize, arr) < 0) {
                ++j;
            }
            if (cmp(v + tmp*elsize, v + a[j]*elsize, arr) < 0) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    for (; n > 1;) {
        tmp = a[n];
        a[n] = a[1];
        n -= 1;
        for (i = 1, j = 2; j <= n;) {
            if (j < n && cmp(v + a[j]*elsize, v + a[j+1]*elsize, arr) < 0) {
                ++j;
            }
            if (cmp(v + tmp*elsize, v + a[j]*elsize, arr) < 0) {
                a[i] = a[j];
                i = j;
                j += j;
            }
            else {
                break;
            }
        }
        a[i] = tmp;
    }

    return 0;
}

