// File: sharmaeklavya2[P]ctmeans/src/lib/ctmeans.cpp
// Function: CTMeans::cluster(bool, int, int, double, _IO_FILE*, int, bool)
double CTMeans::cluster(bool use_kd, int reps, int max_epochs, double obj_tol, FILE* fp, int epoch_interval, bool use_cr) {
    double minobj = std::numeric_limits<double>::infinity();
    std::minstd_rand reng(rand());

    int chars_to_erase = 0;
    char eol = (use_cr?'\r':'\n');
    const char space_str_size = 80;
    char space_str[space_str_size];
    for(int i=0; i<space_str_size; ++i) {
        space_str[i] = ' ';
    }
    space_str[space_str_size-1] = '\0';

    for(int repi=1; repi <= reps; ++repi) {
        init_centroids_rand(reng);
        SigC.push_back(std::vector<int>());
        if(use_kd) {
            P.push_back(std::vector<int>());
        }
        double obj = std::numeric_limits<double>::infinity();
        int epochi;
        for(epochi=0; epochi < max_epochs; ++epochi) {
            double old_obj = obj;
            int sigc;
            int heap_ops;
            obj = step(use_kd, true, false, &sigc, &heap_ops);
            if(use_kd) {
                P.back().push_back(heap_ops);
            }
            SigC.back().push_back(sigc);
            if(fp != nullptr && epochi % epoch_interval == 0) {
                if(use_cr) {
                    space_str[chars_to_erase] = '\0';
                    fprintf(fp, "%s\r", space_str);
                    space_str[chars_to_erase] = ' ';
                }
                chars_to_erase = fprintf(fp, "ctmeans %d-%d: %lg%c", repi, epochi+1, obj, eol);
            }
            if((old_obj - obj) < old_obj * obj_tol) {break;}
        }
        if(fp != nullptr && !use_cr) {
            fprintf(fp, "\n");
        }
        if(obj < minobj) {
            minobj = obj;
            std::swap(minC, C);
        }
    }
    if(fp != nullptr && use_cr) {
        fprintf(fp, "\n");
    }
    C = minC;
    minobj = step(use_kd, false, true);
    return minobj;
}

// Assembly:
subq $0x158, %rsp            # imm = 0x158
movb 0x160(%rsp), %al
movq %rdi, 0x150(%rsp)
andb $0x1, %sil
movb %sil, 0x14f(%rsp)
movl %edx, 0x148(%rsp)
movl %ecx, 0x144(%rsp)
movsd %xmm0, 0x138(%rsp)
movq %r8, 0x130(%rsp)
movl %r9d, 0x12c(%rsp)
andb $0x1, %al
movb %al, 0x12b(%rsp)
movq 0x150(%rsp), %rax
movq %rax, 0x28(%rsp)
callq 0x4540
movsd %xmm0, 0x120(%rsp)
callq 0x2040
movslq %eax, %rsi
leaq 0x118(%rsp), %rdi
callq 0x4550
movl $0x0, 0x114(%rsp)
movb 0x12b(%rsp), %cl
movb $0xd, %al
movb $0xa, %dl
movb %dl, 0x36(%rsp)
testb $0x1, %cl
movb %al, 0x37(%rsp)
jne 0x333d
movb 0x36(%rsp), %al
movb %al, 0x37(%rsp)
movb 0x37(%rsp), %al
movb %al, 0x113(%rsp)
movb $0x50, 0x112(%rsp)
movl $0x0, 0xbc(%rsp)
cmpl $0x50, 0xbc(%rsp)
jge 0x3388
movslq 0xbc(%rsp), %rax
movb $0x20, 0xc0(%rsp,%rax)
movl 0xbc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xbc(%rsp)
jmp 0x335b
movb $0x0, 0x10f(%rsp)
movl $0x1, 0xb8(%rsp)
movl 0xb8(%rsp), %eax
cmpl 0x148(%rsp), %eax
jg 0x36b4
movq 0x28(%rsp), %rdi
leaq 0x118(%rsp), %rsi
callq 0x4580
movq 0x28(%rsp), %rax
addq $0x70, %rax
movq %rax, 0x18(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0xa0(%rsp)
movq $0x0, 0xb0(%rsp)
leaq 0xa0(%rsp), %rdi
movq %rdi, 0x20(%rsp)
callq 0x3e20
movq 0x18(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0x4620
jmp 0x3409
leaq 0xa0(%rsp), %rdi
callq 0x43f0
testb $0x1, 0x14f(%rsp)
je 0x34bd
movq 0x28(%rsp), %rax
addq $0x88, %rax
movq %rax, 0x8(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x70(%rsp)
movq $0x0, 0x80(%rsp)
leaq 0x70(%rsp), %rdi
movq %rdi, 0x10(%rsp)
callq 0x3e20
movq 0x8(%rsp), %rdi
movq 0x10(%rsp), %rsi
callq 0x4620
jmp 0x3468
leaq 0x70(%rsp), %rdi
callq 0x43f0
jmp 0x34bd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x98(%rsp)
movl %eax, 0x94(%rsp)
leaq 0xa0(%rsp), %rdi
callq 0x43f0
jmp 0x3771
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x98(%rsp)
movl %eax, 0x94(%rsp)
leaq 0x70(%rsp), %rdi
callq 0x43f0
jmp 0x3771
callq 0x4540
movsd %xmm0, 0x68(%rsp)
movl $0x0, 0x64(%rsp)
movl 0x64(%rsp), %eax
cmpl 0x144(%rsp), %eax
jge 0x3638
movq 0x28(%rsp), %rdi
movsd 0x68(%rsp), %xmm0
movsd %xmm0, 0x58(%rsp)
movb 0x14f(%rsp), %al
movl $0x1, %edx
xorl %ecx, %ecx
leaq 0x54(%rsp), %r8
leaq 0x50(%rsp), %r9
andb $0x1, %al
movzbl %al, %esi
callq 0x24c0
movsd %xmm0, 0x68(%rsp)
testb $0x1, 0x14f(%rsp)
je 0x3542
movq 0x28(%rsp), %rdi
addq $0x88, %rdi
callq 0x4650
movq %rax, %rdi
leaq 0x50(%rsp), %rsi
callq 0x4190
movq 0x28(%rsp), %rdi
addq $0x70, %rdi
callq 0x4650
movq %rax, %rdi
leaq 0x54(%rsp), %rsi
callq 0x4190
cmpq $0x0, 0x130(%rsp)
je 0x3603
movl 0x64(%rsp), %eax
cltd
idivl 0x12c(%rsp)
cmpl $0x0, %edx
jne 0x3603
testb $0x1, 0x12b(%rsp)
je 0x35c9
movslq 0x114(%rsp), %rax
movb $0x0, 0xc0(%rsp,%rax)
movq 0x130(%rsp), %rdi
leaq 0xc0(%rsp), %rdx
leaq 0x10a8a(%rip), %rsi     # 0x1403c
movb $0x0, %al
callq 0x2220
movslq 0x114(%rsp), %rax
movb $0x20, 0xc0(%rsp,%rax)
movq 0x130(%rsp), %rdi
movl 0xb8(%rsp), %edx
movl 0x64(%rsp), %ecx
addl $0x1, %ecx
movsd 0x68(%rsp), %xmm0
movsbl 0x113(%rsp), %r8d
leaq 0x10a4b(%rip), %rsi     # 0x14040
movb $0x1, %al
callq 0x2220
movl %eax, 0x114(%rsp)
movsd 0x58(%rsp), %xmm1
subsd 0x68(%rsp), %xmm1
movsd 0x58(%rsp), %xmm0
mulsd 0x138(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x3626
jmp 0x3638
jmp 0x3628
movl 0x64(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x64(%rsp)
jmp 0x34d0
cmpq $0x0, 0x130(%rsp)
je 0x3663
testb $0x1, 0x12b(%rsp)
jne 0x3663
movq 0x130(%rsp), %rdi
leaq 0x10a80(%rip), %rsi     # 0x140dc
movb $0x0, %al
callq 0x2220
movsd 0x68(%rsp), %xmm1
movsd 0x120(%rsp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x369c
movq 0x28(%rsp), %rsi
movsd 0x68(%rsp), %xmm0
movsd %xmm0, 0x120(%rsp)
movq %rsi, %rdi
addq $0x40, %rdi
addq $0x28, %rsi
callq 0x4690
jmp 0x369e
movl 0xb8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xb8(%rsp)
jmp 0x339b
cmpq $0x0, 0x130(%rsp)
je 0x36df
testb $0x1, 0x12b(%rsp)
je 0x36df
movq 0x130(%rsp), %rdi
leaq 0x10a04(%rip), %rsi     # 0x140dc
movb $0x0, %al
callq 0x2220
movq 0x28(%rsp), %rsi
addq $0x40, %rsi
leaq 0x38(%rsp), %rdi
movq %rdi, (%rsp)
callq 0x46c0
movq 0x28(%rsp), %rdi
movq (%rsp), %rsi
addq $0x28, %rdi
callq 0x46f0
jmp 0x370a
leaq 0x38(%rsp), %rdi
callq 0x4720
movq 0x28(%rsp), %rdi
movb 0x14f(%rsp), %al
xorl %edx, %edx
movl $0x1, %ecx
xorl %esi, %esi
movl %esi, %r9d
andb $0x1, %al
movzbl %al, %esi
movq %r9, %r8
callq 0x24c0
movsd %xmm0, 0x120(%rsp)
movsd 0x120(%rsp), %xmm0
addq $0x158, %rsp            # imm = 0x158
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x98(%rsp)
movl %eax, 0x94(%rsp)
leaq 0x38(%rsp), %rdi
callq 0x4720
movq 0x98(%rsp), %rdi
callq 0x22a0
nop