#include <stdlib.h>

void            qsortP(void *base, size_t nmemb, size_t size, int (*cmp) (const void *, const void *))
{
    unsigned char  *middle,
                   *last,
                   *left,
                   *right;
    size_t          bytes,
                    two_memb,
                    four_memb,
                    odd_mask;
    struct {
        size_t          bytes;
        void           *base;
    }   stack[32 * sizeof nmemb], *stack_ptr, *stack_limit;

    unsigned char   swap,
                   *p1,
                   *p2;
    size_t          sz;

    if (nmemb > 4) {
        two_memb = size << 1;
        four_memb = two_memb << 1;
        odd_mask = ((size ^ (size - 1)) >> 1) + 1;
        stack->bytes = nmemb * size;
        stack->base = base;
        stack_ptr = stack + 1;
        stack_limit = stack + 5;
        nmemb >>= 3;
        while (nmemb > 0xff >> 1) {
            stack_limit += 8 << 1;
            nmemb >>= 8;
        }
        while (nmemb) {
            stack_limit += 2;
            nmemb >>= 1;
        }
        do {
            --stack_ptr;
            bytes = stack_ptr->bytes;
            if (bytes > four_memb) {
                left = stack_ptr->base;
                if (stack_ptr != stack_limit) {
                    p1 = (left + ((bytes & odd_mask ? bytes - size : bytes) >> 1));
                    p2 = left;
                    sz = size;
                    do {
                        swap = *p1;
                        *p1++ = *p2;
                        *p2++ = swap;
                        --sz;
                    }   while (sz);
                    last = middle = left;
                    right = last += bytes - size;
                    middle += size;
                    if (cmp(middle, left) > 0) {
                        if (cmp(last, left) > 0) {
                            p1 = middle;
                            p2 = left;
                            sz = size;
                            do {
                                swap = *p1;
                                *p1++ = *p2;
                                *p2++ = swap;
                                --sz;
                            }   while (sz);
                            if (cmp(left, last) > 0) {
                                p1 = left;
                                p2 = last;
                                sz = size;
                                do {
                                    swap = *p1;
                                    *p1++ = *p2;
                                    *p2++ = swap;
                                    --sz;
                                }   while (sz);
                            }
                        } else {
                            p1 = middle;
                            p2 = last;
                            sz = size;
                            do {
                                swap = *p1;
                                *p1++ = *p2;
                                *p2++ = swap;
                                --sz;
                            }   while (sz);
                        }
                    } else {
                        if (cmp(left, last) > 0) {
                            p1 = left;
                            p2 = last;
                            sz = size;
                            do {
                                swap = *p1;
                                *p1++ = *p2;
                                *p2++ = swap;
                                --sz;
                            }   while (sz);
                            if (cmp(middle, left) > 0) {
                                p1 = middle;
                                p2 = left;
                                sz = size;
                                do {
                                    swap = *p1;
                                    *p1++ = *p2;
                                    *p2++ = swap;
                                    --sz;
                                }   while (sz);
                            }
                        }
                    }
                    do {
                        middle += size;
                    }   while (cmp(left, middle) > 0);
                    do {
                        last -= size;
                    }   while (cmp(last, left) > 0);
                    while (last > middle) {
                        p1 = middle;
                        p2 = last;
                        sz = size;
                        do {
                            swap = *p1;
                            *p1++ = *p2;
                            *p2++ = swap;
                            --sz;
                        }   while (sz);
                        do {
                            middle += size;
                        }   while (cmp(left, middle) > 0);
                        do {
                            last -= size;
                        }   while (cmp(last, left) > 0);
                    }
                    p1 = left;
                    p2 = last;
                    sz = size;
                    do {
                        swap = *p1;
                        *p1++ = *p2;
                        *p2++ = swap;
                        --sz;
                    }   while (sz);
                    if (right - last > last - left) {
                        stack_ptr->bytes = last - left;
                        stack_ptr->base = left;
                        ++stack_ptr;
                        stack_ptr->bytes = right - last;
                        stack_ptr->base = size + last;
                        ++stack_ptr;
                    } else {
                        stack_ptr->bytes = right - last;
                        stack_ptr->base = size + last;
                        ++stack_ptr;
                        stack_ptr->bytes = last - left;
                        stack_ptr->base = left;
                        ++stack_ptr;
                    }
                } else {
                    unsigned char  *cbase,
                                   *parent,
                                   *child;
                    ptrdiff_t       offset;

                    right = cbase = left;
                    right += bytes - size;
                    left += (bytes & odd_mask
                             ? bytes - size : bytes) >> 1;
                    do {
                        offset = left - cbase;
                        left -= size;
                        parent = child = left;
                        while (right - parent > offset) {
                            child += offset;
                            if (cmp(child + size, child) > 0) {
                                child += size;
                            }
                            if (cmp(child, parent) > 0) {
                                p1 = (parent);
                                p2 = (child);
                                sz = size;
                                do {
                                    swap = *p1;
                                    *p1++ = *p2;
                                    *p2++ = swap;
                                    --sz;
                                }   while (sz);
                                offset = child - cbase + size;
                                parent = child;
                            } else {
                                break;
                            }
                        }
                        if (right - parent == offset
                            && cmp(right, parent) > 0) {
                            p1 = (parent);
                            p2 = right;
                            sz = size;
                            do {
                                swap = *p1;
                                *p1++ = *p2;
                                *p2++ = swap;
                                --sz;
                            }   while (sz);
                        }
                    }   while (left != cbase);
                    do {
                        offset = size;
                        child = parent = cbase;
                        while (right - parent > offset) {
                            child += offset;
                            if (cmp(child + size, child) > 0) {
                                child += size;
                            }
                            p1 = (parent);
                            p2 = (child);
                            sz = size;
                            do {
                                swap = *p1;
                                *p1++ = *p2;
                                *p2++ = swap;
                                --sz;
                            }   while (sz);
                            offset = child - cbase + size;
                            parent = child;
                        }
                        if (parent != right) {
                            p1 = (parent);
                            p2 = right;
                            sz = size;
                            do {
                                swap = *p1;
                                *p1++ = *p2;
                                *p2++ = swap;
                                --sz;
                            }   while (sz);
                            if (right - parent != offset
                                && (parent + size != right
                                    || (offset & odd_mask))) {
                                while (parent != cbase) {
                                    offset = parent - cbase + size;
                                    child = parent;
                                    parent -= (offset & odd_mask
                                             ? size + offset : offset) >> 1;
                                    if (cmp(child, parent) > 0) {
                                        p1 = (parent);
                                        p2 = (child);
                                        sz = size;
                                        do {
                                            swap = *p1;
                                            *p1++ = *p2;
                                            *p2++ = swap;
                                            --sz;
                                        }   while (sz);
                                    } else {
                                        break;
                                    }
                                }
                            }
                        }
                        right -= size;
                    }   while (right != cbase);
                }
            } else {
                if (bytes != size) {
                    left = base = stack_ptr->base;
                    left += size;
                    if (bytes == two_memb) {
                        if (cmp(base, left) > 0) {
                            p1 = base;
                            p2 = left;
                            sz = size;
                            do {
                                swap = *p1;
                                *p1++ = *p2;
                                *p2++ = swap;
                                --sz;
                            }   while (sz);
                        }
                    } else {
                        middle = left + size;
                        if (cmp(base, left) > 0) {
                            if (cmp(middle, left) > 0) {
                                p1 = base;
                                p2 = left;
                                sz = size;
                                do {
                                    swap = *p1;
                                    *p1++ = *p2;
                                    *p2++ = swap;
                                    --sz;
                                }   while (sz);
                                if (cmp(left, middle) > 0) {
                                    p1 = left;
                                    p2 = middle;
                                    sz = size;
                                    do {
                                        swap = *p1;
                                        *p1++ = *p2;
                                        *p2++ = swap;
                                        --sz;
                                    }   while (sz);
                                }
                            } else {
                                p1 = base;
                                p2 = middle;
                                sz = size;
                                do {
                                    swap = *p1;
                                    *p1++ = *p2;
                                    *p2++ = swap;
                                    --sz;
                                }   while (sz);
                            }
                        } else {
                            if (cmp(left, middle) > 0) {
                                p1 = left;
                                p2 = middle;
                                sz = size;
                                do {
                                    swap = *p1;
                                    *p1++ = *p2;
                                    *p2++ = swap;
                                    --sz;
                                }   while (sz);
                                if (cmp(base, left) > 0) {
                                    p1 = base;
                                    p2 = left;
                                    sz = size;
                                    do {
                                        swap = *p1;
                                        *p1++ = *p2;
                                        *p2++ = swap;
                                        --sz;
                                    }   while (sz);
                                }
                            }
                        }
                        if (bytes == four_memb) {
                            right = middle + size;
                            if (cmp(left, right) > 0) {
                                p1 = middle;
                                p2 = right;
                                sz = size;
                                do {
                                    swap = *p1;
                                    *p1++ = *p2;
                                    *p2++ = swap;
                                    --sz;
                                }   while (sz);
                                p1 = left;
                                p2 = middle;
                                sz = size;
                                do {
                                    swap = *p1;
                                    *p1++ = *p2;
                                    *p2++ = swap;
                                    --sz;
                                }   while (sz);
                                if (cmp(base, left) > 0) {
                                    p1 = base;
                                    p2 = left;
                                    sz = size;
                                    do {
                                        swap = *p1;
                                        *p1++ = *p2;
                                        *p2++ = swap;
                                        --sz;
                                    }   while (sz);
                                }
                            } else {
                                if (cmp(middle, right) > 0) {
                                    p1 = middle;
                                    p2 = right;
                                    sz = size;
                                    do {
                                        swap = *p1;
                                        *p1++ = *p2;
                                        *p2++ = swap;
                                        --sz;
                                    }   while (sz);
                                }
                            }
                        }
                    }
                }
            }
        }   while (stack_ptr != stack);
    } else {
        if (nmemb > 1) {
            left = base;
            left += size;
            if (nmemb == 2) {
                if (cmp(base, left) > 0) {
                    p1 = base;
                    p2 = left;
                    sz = size;
                    do {
                        swap = *p1;
                        *p1++ = *p2;
                        *p2++ = swap;
                        --sz;
                    }   while (sz);
                }
            } else {
                middle = left + size;
                if (cmp(base, left) > 0) {
                    if (cmp(middle, left) > 0) {
                        p1 = base;
                        p2 = left;
                        sz = size;
                        do {
                            swap = *p1;
                            *p1++ = *p2;
                            *p2++ = swap;
                            --sz;
                        }   while (sz);
                        if (cmp(left, middle) > 0) {
                            p1 = left;
                            p2 = middle;
                            sz = size;
                            do {
                                swap = *p1;
                                *p1++ = *p2;
                                *p2++ = swap;
                                --sz;
                            }   while (sz);
                        }
                    } else {
                        p1 = base;
                        p2 = middle;
                        sz = size;
                        do {
                            swap = *p1;
                            *p1++ = *p2;
                            *p2++ = swap;
                            --sz;
                        }   while (sz);
                    }
                } else {
                    if (cmp(left, middle) > 0) {
                        p1 = left;
                        p2 = middle;
                        sz = size;
                        do {
                            swap = *p1;
                            *p1++ = *p2;
                            *p2++ = swap;
                            --sz;
                        }   while (sz);
                        if (cmp(base, left) > 0) {
                            p1 = base;
                            p2 = left;
                            sz = size;
                            do {
                                swap = *p1;
                                *p1++ = *p2;
                                *p2++ = swap;
                                --sz;
                            }   while (sz);
                        }
                    }
                }
                if (nmemb == 4) {
                    right = middle + size;
                    if (cmp(left, right) > 0) {
                        p1 = middle;
                        p2 = right;
                        sz = size;
                        do {
                            swap = *p1;
                            *p1++ = *p2;
                            *p2++ = swap;
                            --sz;
                        }   while (sz);
                        p1 = left;
                        p2 = middle;
                        sz = size;
                        do {
                            swap = *p1;
                            *p1++ = *p2;
                            *p2++ = swap;
                            --sz;
                        }   while (sz);
                        if (cmp(base, left) > 0) {
                            p1 = base;
                            p2 = left;
                            sz = size;
                            do {
                                swap = *p1;
                                *p1++ = *p2;
                                *p2++ = swap;
                                --sz;
                            }   while (sz);
                        }
                    } else {
                        if (cmp(middle, right) > 0) {
                            p1 = middle;
                            p2 = right;
                            sz = size;
                            do {
                                swap = *p1;
                                *p1++ = *p2;
                                *p2++ = swap;
                                --sz;
                            }   while (sz);
                        }
                    }
                }
            }
        }
    }
}

