// File: ctSkennerton[P]fxtract/util/rsort.c
// Function: rsort
void
rsort(RSREC ** recv, int nrecs)
{
    int i, k = 256, maxleng = 0;
    int *lengv = calloc(k, sizeof(*lengv));

    for (i = 0; i < nrecs; ++i) {
        int leng = KEYLENG(recv[i]);
        if (leng >= k) {
            int kk = k;
            while (kk <= leng)
                kk <<= 1;
            lengv = realloc(lengv, kk * sizeof(int));
            memset(lengv + k, 0, (kk - k) * sizeof(int));
            k = kk;
        }

        ++lengv[leng];
        if (maxleng < leng)
            maxleng = leng;
    }

    DIAG_NRECS(nrecs);

    if (maxleng == 0) {         // edge case: empty input 
        free(lengv);
        return;
    }

    int pos = 0, nsrcs = 1, skip;
    PART *pdata = malloc((nrecs + 1) * sizeof(PART));
    PARTNO *partv = malloc(MAXPARTS * sizeof(*partv));
    int rsize = ((nrecs - 1) / MINRANGE + 1) * sizeof(RANGE);
    RANGE *srcv = malloc(rsize);
    RANGE *dstv = malloc(rsize);
    PARTNO *mapv[maxleng + 1];
    PARTNO mdata[MAXMAPS][256];

    for (i = 0; i <= maxleng; ++i)
        mapv[i] = 0;
    for (i = 1; i < MAXMAPS; ++i)
        *mdata[i] = UNUSED;

    // mdata[0] is permanently all 0. It is used to "map"
    //        bytes in the middle of the range (pos;len) that
    //        have exactly one value.
    memset(mdata[0], 0, sizeof(mdata[0]));

    // pdata[0]: a dummy list terminator; simplifies a loop 
    pdata[0] = (PART) { 0, NULL, NULL};

    // Initial srcv: a single range of the entire input 
    srcv[0] = (RANGE) {recv, recv + nrecs};
    for (pos = 0; nsrcs; pos += skip) {
        int len, nparts;

        DIAG_TICK(t1);
        nparts = analyze(maxleng, lengv, nsrcs, srcv,
                         mapv, mdata, &pos, &skip, &len);
        DIAG_TICK(t2);

        // Initialize partv[] to the index of dummy pdata[0]. 
        for (i = 0; i < nparts; ++i)
            partv[i] = 0;

        scatter(nsrcs, srcv, pos, len, mapv, partv, pdata);

        for (i = 0; i < len; ++i)
            *mapv[pos + i] = UNUSED;
        mdata[0][0] = 0;        // Undo "freeing" of mdata[0] 
#if DIAG
        int maxpart = -1;
        for (i = k = 0; i < nparts; ++i) {
            k += !!partv[i];
            if (partv[i]) maxpart = i;
        }
        fprintf(stderr, "# %9d recs %5d rngs on"
                " %d:%d%s %d/%d parts max=%d",
                _nrecs, nsrcs, pos, pos + len - 1,
                len == skip ? "" : "+", k, nparts, maxpart);
        DIAG_TICK(t3);
        DIAG_NRECS(0);          // updated by gather() 
#endif
        nsrcs = gather(pos + skip, nparts, partv, pdata, dstv);
#if DIAG
        fprintf(stderr, "\t%.3f %.3f %.3f secs\n",
                t2 - t1, t3 - t2, tick() - t3);
#endif
        RANGE *tmp = srcv;
        srcv = dstv;
        dstv = tmp;
    }

    free(dstv);
    free(srcv);
    free(partv);
    free(pdata);
    free(lengv);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %rbx
subq $0x84f8, %rsp           # imm = 0x84F8
movq %rdi, -0x10(%rbp)
movl %esi, -0x14(%rbp)
movl $0x100, -0x1c(%rbp)     # imm = 0x100
movl $0x0, -0x20(%rbp)
movslq -0x1c(%rbp), %rdi
movl $0x4, %esi
callq 0x3130
movq %rax, -0x28(%rbp)
movl $0x0, -0x18(%rbp)
movl -0x18(%rbp), %eax
cmpl -0x14(%rbp), %eax
jge 0x5db7
movq -0x10(%rbp), %rax
movslq -0x18(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
callq 0x6260
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jl 0x5d88
movl -0x1c(%rbp), %eax
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %eax
cmpl -0x2c(%rbp), %eax
jg 0x5d4a
movl -0x30(%rbp), %eax
shll %eax
movl %eax, -0x30(%rbp)
jmp 0x5d38
movq -0x28(%rbp), %rdi
movslq -0x30(%rbp), %rsi
shlq $0x2, %rsi
callq 0x3300
movq %rax, -0x28(%rbp)
movq -0x28(%rbp), %rdi
movslq -0x1c(%rbp), %rax
shlq $0x2, %rax
addq %rax, %rdi
movl -0x30(%rbp), %eax
subl -0x1c(%rbp), %eax
movslq %eax, %rdx
shlq $0x2, %rdx
xorl %esi, %esi
callq 0x30f0
movl -0x30(%rbp), %eax
movl %eax, -0x1c(%rbp)
movq -0x28(%rbp), %rax
movslq -0x2c(%rbp), %rcx
movl (%rax,%rcx,4), %edx
addl $0x1, %edx
movl %edx, (%rax,%rcx,4)
movl -0x20(%rbp), %eax
cmpl -0x2c(%rbp), %eax
jge 0x5da7
movl -0x2c(%rbp), %eax
movl %eax, -0x20(%rbp)
jmp 0x5da9
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x5d0a
movl -0x14(%rbp), %eax
movl %eax, 0x59e0(%rip)      # 0xb7a0
cmpl $0x0, -0x20(%rbp)
jne 0x5dd4
movq -0x28(%rbp), %rdi
callq 0x3230
jmp 0x6257
movl $0x0, -0x34(%rbp)
movl $0x1, -0x38(%rbp)
movslq -0x14(%rbp), %rax
shlq $0x3, %rax
leaq 0x18(%rax,%rax,2), %rdi
callq 0x3260
movq %rax, -0x48(%rbp)
movl $0x42744, %edi          # imm = 0x42744
callq 0x3260
movq %rax, -0x50(%rbp)
movl -0x14(%rbp), %ecx
movl %ecx, %eax
decl %eax
addl $0xe, %ecx
testl %eax, %eax
cmovsl %ecx, %eax
andl $-0x10, %eax
addl $0x10, %eax
movl %eax, -0x54(%rbp)
movslq -0x54(%rbp), %rdi
callq 0x3260
movq %rax, -0x60(%rbp)
movslq -0x54(%rbp), %rdi
callq 0x3260
movq %rax, -0x68(%rbp)
movl -0x20(%rbp), %eax
incl %eax
movq %rsp, %rcx
movq %rcx, -0x70(%rbp)
leaq 0xf(,%rax,8), %rdx
andq $-0x10, %rdx
movq %rsp, %rcx
subq %rdx, %rcx
movq %rcx, -0x84e0(%rbp)
movq %rcx, %rsp
movq %rax, -0x78(%rbp)
movl $0x0, -0x18(%rbp)
movl -0x18(%rbp), %eax
cmpl -0x20(%rbp), %eax
jg 0x5e91
movq -0x84e0(%rbp), %rax
movslq -0x18(%rbp), %rcx
movq $0x0, (%rax,%rcx,8)
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x5e6b
movl $0x1, -0x18(%rbp)
cmpl $0x21, -0x18(%rbp)
jge 0x5ec1
movslq -0x18(%rbp), %rcx
leaq -0x8480(%rbp), %rax
shlq $0xa, %rcx
addq %rcx, %rax
movl $0x109d1, (%rax)        # imm = 0x109D1
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x5e98
leaq -0x8480(%rbp), %rdi
xorl %esi, %esi
movl $0x400, %edx            # imm = 0x400
callq 0x30f0
movq -0x48(%rbp), %rax
movq %rax, -0x84e8(%rbp)
leaq -0x8498(%rbp), %rdi
xorl %esi, %esi
movl $0x18, %edx
callq 0x30f0
movq -0x84e8(%rbp), %rax
movq -0x8498(%rbp), %rcx
movq %rcx, (%rax)
movq -0x8490(%rbp), %rcx
movq %rcx, 0x8(%rax)
movq -0x8488(%rbp), %rcx
movq %rcx, 0x10(%rax)
movq -0x60(%rbp), %rax
movq -0x10(%rbp), %rcx
movq %rcx, -0x84a8(%rbp)
movq -0x10(%rbp), %rcx
movslq -0x14(%rbp), %rdx
shlq $0x3, %rdx
addq %rdx, %rcx
movq %rcx, -0x84a0(%rbp)
movq -0x84a8(%rbp), %rcx
movq %rcx, (%rax)
movq -0x84a0(%rbp), %rcx
movq %rcx, 0x8(%rax)
movl $0x0, -0x34(%rbp)
cmpl $0x0, -0x38(%rbp)
je 0x6223
callq 0x6280
movq -0x84e0(%rbp), %r8
movsd %xmm0, -0x84b8(%rbp)
movl -0x20(%rbp), %edi
movq -0x28(%rbp), %rsi
movl -0x38(%rbp), %edx
movq -0x60(%rbp), %rcx
leaq -0x8480(%rbp), %r9
leaq -0x34(%rbp), %r11
leaq -0x3c(%rbp), %r10
leaq -0x84ac(%rbp), %rax
subq $0x20, %rsp
movq %r11, (%rsp)
movq %r10, 0x8(%rsp)
movq %rax, 0x10(%rsp)
callq 0x62c0
addq $0x20, %rsp
movl %eax, -0x84b0(%rbp)
callq 0x6280
movsd %xmm0, -0x84c0(%rbp)
movl $0x0, -0x18(%rbp)
movl -0x18(%rbp), %eax
cmpl -0x84b0(%rbp), %eax
jge 0x5ff6
movq -0x50(%rbp), %rax
movslq -0x18(%rbp), %rcx
movl $0x0, (%rax,%rcx,4)
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x5fd1
movq -0x84e0(%rbp), %r8
movl -0x38(%rbp), %edi
movq -0x60(%rbp), %rsi
movl -0x34(%rbp), %edx
movl -0x84ac(%rbp), %ecx
movq -0x50(%rbp), %r9
movq -0x48(%rbp), %rax
subq $0x10, %rsp
movq %rax, (%rsp)
callq 0x6590
addq $0x10, %rsp
movl $0x0, -0x18(%rbp)
movl -0x18(%rbp), %eax
cmpl -0x84ac(%rbp), %eax
jge 0x605d
movq -0x84e0(%rbp), %rax
movl -0x34(%rbp), %ecx
addl -0x18(%rbp), %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movl $0x109d1, (%rax)        # imm = 0x109D1
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x602d
movl $0x0, -0x8480(%rbp)
movl $0xffffffff, -0x84c4(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0x1c(%rbp)
movl $0x0, -0x18(%rbp)
movl -0x18(%rbp), %eax
cmpl -0x84b0(%rbp), %eax
jge 0x60cc
movq -0x50(%rbp), %rax
movslq -0x18(%rbp), %rcx
cmpl $0x0, (%rax,%rcx,4)
setne %al
xorb $-0x1, %al
xorb $-0x1, %al
andb $0x1, %al
movzbl %al, %eax
addl -0x1c(%rbp), %eax
movl %eax, -0x1c(%rbp)
movq -0x50(%rbp), %rax
movslq -0x18(%rbp), %rcx
cmpl $0x0, (%rax,%rcx,4)
je 0x60bf
movl -0x18(%rbp), %eax
movl %eax, -0x84c4(%rbp)
jmp 0x60c1
movl -0x18(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x18(%rbp)
jmp 0x607f
movq 0x4f0d(%rip), %rax      # 0xafe0
movq (%rax), %rdi
movl 0x56c4(%rip), %edx      # 0xb7a0
movl -0x38(%rbp), %ecx
movl -0x34(%rbp), %r8d
movl -0x34(%rbp), %r9d
addl -0x84ac(%rbp), %r9d
subl $0x1, %r9d
movl -0x84ac(%rbp), %esi
movl -0x3c(%rbp), %r10d
leaq 0x201b(%rip), %rbx      # 0x811e
leaq 0x27e4(%rip), %rax      # 0x88ee
cmpl %r10d, %esi
cmoveq %rax, %rbx
movl -0x1c(%rbp), %r11d
movl -0x84b0(%rbp), %r10d
movl -0x84c4(%rbp), %eax
leaq 0x1fc3(%rip), %rsi      # 0x80ec
subq $0x20, %rsp
movq %rbx, (%rsp)
movl %r11d, 0x8(%rsp)
movl %r10d, 0x10(%rsp)
movl %eax, 0x18(%rsp)
movb $0x0, %al
callq 0x32a0
addq $0x20, %rsp
callq 0x6280
movsd %xmm0, -0x84d0(%rbp)
movl $0x0, 0x563f(%rip)      # 0xb7a0
movl -0x34(%rbp), %edi
addl -0x3c(%rbp), %edi
movl -0x84b0(%rbp), %esi
movq -0x50(%rbp), %rdx
movq -0x48(%rbp), %rcx
movq -0x68(%rbp), %r8
callq 0x6780
movl %eax, -0x38(%rbp)
movq 0x4e58(%rip), %rax      # 0xafe0
movq (%rax), %rax
movq %rax, -0x8500(%rbp)
movsd -0x84c0(%rbp), %xmm0
subsd -0x84b8(%rbp), %xmm0
movsd %xmm0, -0x84f0(%rbp)
movsd -0x84d0(%rbp), %xmm0
subsd -0x84c0(%rbp), %xmm0
movsd %xmm0, -0x84f8(%rbp)
callq 0x6280
movq -0x8500(%rbp), %rdi
movsd -0x84f8(%rbp), %xmm1
movaps %xmm0, %xmm2
movsd -0x84f0(%rbp), %xmm0
subsd -0x84d0(%rbp), %xmm2
leaq 0x1f30(%rip), %rsi      # 0x8120
movb $0x3, %al
callq 0x32a0
movq -0x60(%rbp), %rax
movq %rax, -0x84d8(%rbp)
movq -0x68(%rbp), %rax
movq %rax, -0x60(%rbp)
movq -0x84d8(%rbp), %rax
movq %rax, -0x68(%rbp)
movl -0x3c(%rbp), %eax
addl -0x34(%rbp), %eax
movl %eax, -0x34(%rbp)
jmp 0x5f5a
movq -0x68(%rbp), %rdi
callq 0x3230
movq -0x60(%rbp), %rdi
callq 0x3230
movq -0x50(%rbp), %rdi
callq 0x3230
movq -0x48(%rbp), %rdi
callq 0x3230
movq -0x28(%rbp), %rdi
callq 0x3230
movq -0x70(%rbp), %rax
movq %rax, %rsp
leaq -0x8(%rbp), %rsp
popq %rbx
popq %rbp
retq
nop