// File: /workspace/github_c_makefile_star2_O0/skeeto[P]hash-prospector/hp16.c
// Function: main
int
main(int argc, char **argv)
{
    char *ptr;
    int n = 0;
    int exclude = 0;
    enum {
        MODE_HASH, MODE_SMART, MODE_XORMUL, MODE_SBOX, MODE_AXS
    } mode = MODE_HASH;
    unsigned long tmp;
    struct hf_op ops[1+2*OPS_MAX] = {{HF16_SBOX, 0}};

    int option;
    while ((option = xgetopt(argc, argv, "AHhImn:rSX")) != -1) {
        switch (option) {
        case 'A':
            mode = MODE_AXS;
            break;
        case 'H':
            mode = MODE_HASH;
            break;
        case 'h':
            usage(stdout);
            return 0;
        case 'I':
            mode = MODE_SMART;
            break;
        case 'm':
            exclude |= 1<<HF16_MUL;
            break;
        case 'n':
            tmp = strtoul(xoptarg, &ptr, 10);
            if (!tmp || *ptr || tmp > OPS_MAX) {
                fprintf(stderr, "fatal: invalid n, %s\n", xoptarg);
                usage(stderr);
                return 1;
            }
            n = tmp;
            break;
        case 'r':
            exclude |= 1<<HF16_ROT;
            break;
        case 'S':
            mode = MODE_SBOX;
            break;
        case 'X':
            mode = MODE_XORMUL;
            break;
        case '?':
            usage(stderr);
            return 1;
        }
    }

    switch (mode) {
    case MODE_HASH:
    case MODE_SMART:  n = n ? n : 7; break;
    case MODE_XORMUL: n = n ? 1 + 2*n : 5; break;
    case MODE_SBOX:   sbox_init(); n = 1; break;
    case MODE_AXS:    break;
    }

    double best = 1;
    unsigned long long s[1] = {hash64(time(0))};

    if (mode == MODE_AXS) {
        #pragma omp parallel for
        for (long i = 0; i < AXS_COUNT; i++) {
            struct hf_op hf[AXS_SIZE];
            hf_genaxs(hf, i);
            double r = score(hf, AXS_SIZE);
            #pragma omp critical
            if (r < best) {
                best = r;
                printf("// bias = %.17g\n", r);
                hf_print(hf, AXS_SIZE, stdout);
                fputc('\n', stdout);
                fflush(stdout);
            }
        }
        return 0;
    }

    for (;;) {
        *s += hash64(time(0));
        switch (mode) {
        case MODE_HASH:
            do {
                hf_genfunc(ops, n, s);
            } while (match(ops, n, exclude));
            break;
        case MODE_SMART:
            do {
                hf_gensmart(ops, n, s);
            } while (match(ops, n, exclude));
            break;
        case MODE_XORMUL:
            hf_genxormul(ops, (n-1)/2, s);
            break;
        case MODE_SBOX:
            sbox_shuffle(s);
            break;
        case MODE_AXS:
            abort();
        }
        *s -= hash64(clock());

        double r = score(ops, n);
        if (r < best) {
            switch (mode) {
            case MODE_HASH:
            case MODE_SMART:
            case MODE_XORMUL:
                printf("// bias = %.17g\n", r);
                hf_print(ops, n, stdout);
                fputc('\n', stdout);
                break;
            case MODE_SBOX:
                fprintf(stdout, "// bias = %.17g\n", r);
                sbox_print(stdout);
                fputc('\n', stdout);
                fprintf(stderr, "// bias = %.17g\n", r);
                fflush(stderr);
                break;
            case MODE_AXS:
                abort();
            }
            fflush(stdout);
            best = r;
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x2d0, %rsp            # imm = 0x2D0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x0, -0x1c(%rbp)
movl $0x0, -0x20(%rbp)
movl $0x0, -0x24(%rbp)
leaq -0x240(%rbp), %rdi
xorl %esi, %esi
movl $0x208, %edx            # imm = 0x208
callq 0x1080
movl $0x9, -0x240(%rbp)
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0x1f4f(%rip), %rdx      # 0x31b8
callq 0x17c0
movl %eax, -0x244(%rbp)
cmpl $-0x1, %eax
je 0x13af
movl -0x244(%rbp), %eax
addl $-0x3f, %eax
movl %eax, %ecx
movq %rcx, -0x2a8(%rbp)
subl $0x33, %eax
ja 0x13aa
movq -0x2a8(%rbp), %rax
leaq 0x1da2(%rip), %rcx      # 0x3048
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movl $0x4, -0x24(%rbp)
jmp 0x13aa
movl $0x0, -0x24(%rbp)
jmp 0x13aa
movq 0x3d0a(%rip), %rax      # 0x4fd8
movq (%rax), %rdi
callq 0x1a60
movl $0x0, -0x4(%rbp)
jmp 0x17a7
movl $0x1, -0x24(%rbp)
jmp 0x13aa
movl -0x20(%rbp), %eax
orl $0x2, %eax
movl %eax, -0x20(%rbp)
jmp 0x13aa
movq 0x3dbd(%rip), %rdi      # 0x50c0
leaq -0x18(%rbp), %rsi
movl $0xa, %edx
callq 0x10e0
movq %rax, -0x30(%rbp)
cmpq $0x0, -0x30(%rbp)
je 0x132f
movq -0x18(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x0, %eax
jne 0x132f
cmpq $0x20, -0x30(%rbp)
jbe 0x1369
movq 0x3cc2(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
movq 0x3d80(%rip), %rdx      # 0x50c0
leaq 0x1e7c(%rip), %rsi      # 0x31c3
movb $0x0, %al
callq 0x10b0
movq 0x3ca3(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
callq 0x1a60
movl $0x1, -0x4(%rbp)
jmp 0x17a7
movq -0x30(%rbp), %rax
movl %eax, -0x1c(%rbp)
jmp 0x13aa
movl -0x20(%rbp), %eax
orl $0x8, %eax
movl %eax, -0x20(%rbp)
jmp 0x13aa
movl $0x3, -0x24(%rbp)
jmp 0x13aa
movl $0x2, -0x24(%rbp)
jmp 0x13aa
movq 0x3c62(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
callq 0x1a60
movl $0x1, -0x4(%rbp)
jmp 0x17a7
jmp 0x125b
movl -0x24(%rbp), %eax
movq %rax, -0x2b0(%rbp)
subq $0x4, %rax
ja 0x143d
movq -0x2b0(%rbp), %rax
leaq 0x1c53(%rip), %rcx      # 0x3020
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
cmpl $0x0, -0x1c(%rbp)
je 0x13e7
movl -0x1c(%rbp), %eax
movl %eax, -0x2b4(%rbp)
jmp 0x13f4
movl $0x7, %eax
movl %eax, -0x2b4(%rbp)
jmp 0x13f4
movl -0x2b4(%rbp), %eax
movl %eax, -0x1c(%rbp)
jmp 0x143d
cmpl $0x0, -0x1c(%rbp)
je 0x1415
movl -0x1c(%rbp), %eax
shll %eax
addl $0x1, %eax
movl %eax, -0x2b8(%rbp)
jmp 0x1422
movl $0x5, %eax
movl %eax, -0x2b8(%rbp)
jmp 0x1422
movl -0x2b8(%rbp), %eax
movl %eax, -0x1c(%rbp)
jmp 0x143d
callq 0x1b30
movl $0x1, -0x1c(%rbp)
jmp 0x143d
jmp 0x143d
movsd 0x1bc3(%rip), %xmm0     # 0x3008
movsd %xmm0, -0x250(%rbp)
xorl %eax, %eax
movl %eax, %edi
callq 0x10c0
movq %rax, %rdi
callq 0x1b70
movq %rax, -0x258(%rbp)
cmpl $0x4, -0x24(%rbp)
jne 0x1556
movq $0x0, -0x260(%rbp)
cmpq $0xadcea10, -0x260(%rbp) # imm = 0xADCEA10
jge 0x154a
leaq -0x290(%rbp), %rdi
movq -0x260(%rbp), %rsi
callq 0x1bf0
leaq -0x290(%rbp), %rdi
movl $0x6, %esi
callq 0x1e00
movsd %xmm0, -0x298(%rbp)
movsd -0x298(%rbp), %xmm1
movsd -0x250(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x1531
movsd -0x298(%rbp), %xmm0
movsd %xmm0, -0x250(%rbp)
movsd -0x298(%rbp), %xmm0
leaq 0x1ced(%rip), %rdi      # 0x31d9
movb $0x1, %al
callq 0x1060
leaq -0x290(%rbp), %rdi
movq 0x3ad7(%rip), %rax      # 0x4fd8
movq (%rax), %rdx
movl $0x6, %esi
callq 0x2030
movq 0x3ac3(%rip), %rax      # 0x4fd8
movq (%rax), %rsi
movl $0xa, %edi
callq 0x1090
movq 0x3aaf(%rip), %rax      # 0x4fd8
movq (%rax), %rdi
callq 0x10d0
jmp 0x1533
movq -0x260(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x260(%rbp)
jmp 0x147a
movl $0x0, -0x4(%rbp)
jmp 0x17a7
jmp 0x1558
xorl %eax, %eax
movl %eax, %edi
callq 0x10c0
movq %rax, %rdi
callq 0x1b70
movq %rax, %rcx
movq -0x258(%rbp), %rax
addq %rcx, %rax
movq %rax, -0x258(%rbp)
movl -0x24(%rbp), %eax
movq %rax, -0x2c0(%rbp)
subq $0x4, %rax
ja 0x1642
movq -0x2c0(%rbp), %rax
leaq 0x1a95(%rip), %rcx      # 0x3034
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
jmp 0x15aa
leaq -0x240(%rbp), %rdi
movl -0x1c(%rbp), %esi
leaq -0x258(%rbp), %rdx
callq 0x2240
leaq -0x240(%rbp), %rdi
movl -0x1c(%rbp), %esi
movl -0x20(%rbp), %edx
callq 0x2310
cmpl $0x0, %eax
jne 0x15aa
jmp 0x1642
jmp 0x15db
leaq -0x240(%rbp), %rdi
movl -0x1c(%rbp), %esi
leaq -0x258(%rbp), %rdx
callq 0x2370
leaq -0x240(%rbp), %rdi
movl -0x1c(%rbp), %esi
movl -0x20(%rbp), %edx
callq 0x2310
cmpl $0x0, %eax
jne 0x15db
jmp 0x1642
leaq -0x240(%rbp), %rdi
movl -0x1c(%rbp), %eax
subl $0x1, %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %esi
leaq -0x258(%rbp), %rdx
callq 0x2450
jmp 0x1642
leaq -0x258(%rbp), %rdi
callq 0x2540
jmp 0x1642
callq 0x1030
callq 0x1040
movq %rax, %rdi
callq 0x1b70
movq %rax, %rcx
movq -0x258(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x258(%rbp)
leaq -0x240(%rbp), %rdi
movl -0x1c(%rbp), %esi
callq 0x1e00
movsd %xmm0, -0x2a0(%rbp)
movsd -0x2a0(%rbp), %xmm1
movsd -0x250(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x17a2
movl -0x24(%rbp), %eax
movl %eax, -0x2c4(%rbp)
subl $0x3, %eax
jb 0x16c5
jmp 0x16a4
movl -0x2c4(%rbp), %eax
subl $0x3, %eax
je 0x170a
jmp 0x16b1
movl -0x2c4(%rbp), %eax
subl $0x4, %eax
je 0x177e
jmp 0x1783
movsd -0x2a0(%rbp), %xmm0
leaq 0x1b05(%rip), %rdi      # 0x31d9
movb $0x1, %al
callq 0x1060
leaq -0x240(%rbp), %rdi
movl -0x1c(%rbp), %esi
movq 0x38ec(%rip), %rax      # 0x4fd8
movq (%rax), %rdx
callq 0x2030
movq 0x38dd(%rip), %rax      # 0x4fd8
movq (%rax), %rsi
movl $0xa, %edi
callq 0x1090
jmp 0x1783
movq 0x38c7(%rip), %rax      # 0x4fd8
movq (%rax), %rdi
movsd -0x2a0(%rbp), %xmm0
leaq 0x1ab6(%rip), %rsi      # 0x31d9
movb $0x1, %al
callq 0x10b0
movq 0x38a7(%rip), %rax      # 0x4fd8
movq (%rax), %rdi
callq 0x25d0
movq 0x3898(%rip), %rax      # 0x4fd8
movq (%rax), %rsi
movl $0xa, %edi
callq 0x1090
movq 0x38a4(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
movsd -0x2a0(%rbp), %xmm0
leaq 0x1a73(%rip), %rsi      # 0x31d9
movb $0x1, %al
callq 0x10b0
movq 0x3884(%rip), %rax      # 0x4ff8
movq (%rax), %rdi
callq 0x10d0
jmp 0x1783
callq 0x1030
movq 0x384e(%rip), %rax      # 0x4fd8
movq (%rax), %rdi
callq 0x10d0
movsd -0x2a0(%rbp), %xmm0
movsd %xmm0, -0x250(%rbp)
jmp 0x1558
movl -0x4(%rbp), %eax
addq $0x2d0, %rsp            # imm = 0x2D0
popq %rbp
retq
nopw %cs:(%rax,%rax)