// File: /workspace/github_cpp_makefile_star2_O3/funny-falcon[P]fanom_hash/test_fanom.cpp
// Function: main
int main(int argc, char** argv) {
	unsigned i;
	int hex = 0;
	int use_std = 0;
	int check = 0;
	int binary = 0;
	int only_hash = 2;
	uint32_t sum = 0;
	ssize_t lsize;
	char *lbuf = NULL;
	size_t lcapa = 0;
	FILE* r;
	table tbl = {0, 0, NULL};
	std::unordered_set<std::string> set;

	for (i=1; i<argc; i++) {
		if (strcmp(argv[i], "--help") == 0) {
			goto usage;
		} else if (strcmp(argv[i], "-s") == 0) {
			use_std = 1;
		} else if (strcmp(argv[i], "-c") == 0) {
			check = 1;
		} else if (strcmp(argv[i], "-32") == 0) {
			use_32 = 1;
		} else if (strcmp(argv[i], "-x") == 0) {
			hex = 1;
			fill_dehex();
		} else if (strcmp(argv[i], "-r") == 0) {
			custom_seed = -1;
		} else if (strcmp(argv[i], "-speed") == 0) {
			only_hash = 1;
		} else if (strcmp(argv[i], "-table") == 0) {
			only_hash = 0;
		} else if (strcmp(argv[i], "-seed") == 0) {
			uint64_t s;
			i++;
			if (i == argc)
				goto usage;
			if (custom_seed == sizeof(seed)/sizeof(seed[0]))
				goto usage;
			s = strtoll(argv[i], NULL, 0); /* strtol recognize hex */
			seed[custom_seed++] = s;
		} else if (strcmp(argv[i], "-b") == 0) {
			i++;
			if (i == argc)
				goto usage;
			binary = atoi(argv[i]);
		} else {
			goto usage;
		}
	}

	if (only_hash != 2) {
		setbuffer(stdin, buffer, sizeof(buffer));
	}

	if (custom_seed == 0 && !only_hash || custom_seed == -1) {
		r = fopen("/dev/urandom", "rb");
		if (r == NULL) {
			perror("open /dev/urandom");
			return 1;
		}
		if (fread(&seed, sizeof(seed), 1, r) != 1) {
			perror("Could not read seed from /dev/urandom");
			return 1;
		}
		fclose(r);
	} else if (custom_seed == 1) {
		const uint64_t c = ((uint64_t)0x6385a7c9<<32)|0xeb0d2f41;
		seed[1] = seed[0] ^ c;
	}
	

	if (binary) {
		lbuf = (char*)malloc(binary+1);
		while ((lsize = fread(lbuf, 1, binary, stdin)) > 0) {
			if (only_hash) {
				uint64_t hash;
				if (use_32 == 0) {
					hash = fanom64_string_hash2(lbuf, lsize, seed[0], seed[1]);
				} else {
					hash = fanom32_string_hash2(lbuf, lsize, seed[0], seed[1]);
				}
				if (only_hash == 2) {
					printf("%0*" PRIx64 "\n", use_32?8:16, hash);
				}
				sum += hash;
			} else if (use_std == 0) {
				table_insert(&tbl, lbuf, lsize);
			} else {
				set.insert(std::string(lbuf, lsize));
			}
		}
	} else {
		char* copy;
		while ((lsize = getline(&lbuf, &lcapa, stdin)) != -1) {
			lsize--;
			if (only_hash == 2) {
				copy = strndup(lbuf, lsize);
			}
			if (hex) {
				assert((lsize&1) == 0);
				dehexify(lbuf, lsize);
				lsize /= 2;
			}
			if (only_hash) {
				uint64_t hash;
				if (use_32 == 0) {
					hash = fanom64_string_hash2(lbuf, lsize, seed[0], seed[1]);
				} else {
					hash = fanom32_string_hash2(lbuf, lsize, seed[0], seed[1]);
				}
				if (only_hash == 2) {
					printf("%0*" PRIx64 "\t%s\n", use_32?8:16, hash, copy);
					free(copy);
				}
				sum += hash;
			} else if (use_std == 0) {
				table_insert(&tbl, lbuf, lsize);
			} else {
				set.insert(std::string(lbuf, lsize));
			}
		}
	}

	if (only_hash) {
		if (only_hash == 1)
			printf("Sum = %x\n", sum);
		return 0;
	}

	if (use_std == 0) {
		if (tbl.size == 0) {
			goto usage;
		}

		printf("tbl->size == %u\n", tbl.size);
		if (check) {
			return check_table(&tbl, use_32);
		}
	} else {
		if (set.size() == 0) {
			goto usage;
		}
		printf("tbl->size == %zu\n", set.size());
		if (check) {
			for (auto& s: set) {
				checksum_add(s.data(), s.size());
			}
			printf("checksum %08x %08x\n", checksum[0], checksum[1]);
		}
	}
	return 0;
usage:
	printf("Usage: %s [-seed N] [-x] [-b N] [-32] [-speed|-table] [-s] [-c] < input_file\n%s", argv[0],
	"  Default, \"test vector mode\": reads lines from stdin and report checksum for every line.\n" \
	"  With -speed , only checksumming performed.\n" \
	"  With -table , puts them into chained hash table, on exit it \n" \
	"    calculates and outputs checksum and table size.\n" \
	"\t--help  - this help.\n" \
	"\t-seed N - use custom seed instead of random.\n" \
	"\t          Every invocation fills next seed array element,\n" \
	"\t          so you may give this option 1 or 2 times.\n" \
	"\t-b N    - input is binary, slice it to chunks of fixed size N\n" \
	"\t-x      - input lines are hexified, so de-hexify it\n" \
	"\t-r      - force random seed for \"test vector\"\n" \
	"\t-32     - use 32bit fanom hash function\n" \
	"\t-speed  - test speed only\n" \
	"\t-table  - test hash table (all options below for this mode)\n" \
	"\t-s      - use c++ set to verify hash table implementation\n" \
	"\t-c      - at the end, detect collisions and chain length, and\n" \
	"\t          calculate independent checksum for all inserted strings\n");
	printf("  example for \"test vector\":\n" \
		"\t%s < test_fansom.cpp\n" \
		"\techo 'a1b2bc3def' | %s \n" \
		"\techo 'a1b2bc3def' | %s -seed 2 -seed 3\n" \
		"\techo 'a1b2bc3def' | %s -x -seed 2 -seed 3\n",
		argv[0], argv[0], argv[0], argv[0]
		);
	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xb8, %rsp
movq %rsi, 0x30(%rsp)
xorl %r13d, %r13d
movq %r13, 0x10(%rsp)
movq %r13, 0x78(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x60(%rsp)
leaq 0xb0(%rsp), %rax
movq %rax, -0x30(%rax)
movq $0x1, -0x28(%rax)
movups %xmm0, -0x20(%rax)
movl $0x3f800000, -0x10(%rax) # imm = 0x3F800000
movups %xmm0, -0x8(%rax)
movl $0x2, %r12d
movb $0x1, %al
movl %eax, 0x1c(%rsp)
cmpl $0x2, %edi
jb 0x2b38
movl %edi, %ebp
movq $0x0, 0x28(%rsp)
movl $0x1, %r14d
movl $0x0, 0x20(%rsp)
movl $0x0, 0xc(%rsp)
xorl %r13d, %r13d
movl %r14d, %eax
movq 0x30(%rsp), %rcx
movq (%rcx,%rax,8), %rbx
movq %rbx, %rdi
leaq 0x183e(%rip), %rsi      # 0x417b
callq 0x21f0
testl %eax, %eax
je 0x2f40
movb (%rbx), %r15b
cmpb $0x2d, %r15b
jne 0x2993
cmpb $0x73, 0x1(%rbx)
jne 0x2963
cmpb $0x0, 0x2(%rbx)
je 0x2a95
cmpb $0x63, 0x1(%rbx)
jne 0x2a32
cmpb $0x0, 0x2(%rbx)
je 0x2a9f
movq %rbx, %rdi
leaq 0x1801(%rip), %rsi      # 0x4182
callq 0x21f0
testl %eax, %eax
jne 0x2a4f
jmp 0x2a7f
movq %rbx, %rdi
leaq 0x17e5(%rip), %rsi      # 0x4182
callq 0x21f0
testl %eax, %eax
je 0x2a7f
movq %rbx, %rdi
leaq 0x17d2(%rip), %rsi      # 0x4186
callq 0x21f0
testl %eax, %eax
je 0x2a88
movq %rbx, %rdi
leaq 0x17c2(%rip), %rsi      # 0x418d
callq 0x21f0
testl %eax, %eax
je 0x2a90
movq %rbx, %rdi
leaq 0x17b2(%rip), %rsi      # 0x4194
callq 0x21f0
testl %eax, %eax
je 0x2aa9
cmpb $0x2d, %r15b
jne 0x2f40
cmpb $0x62, 0x1(%rbx)
jne 0x2f40
cmpb $0x0, 0x2(%rbx)
jne 0x2f40
incl %r14d
cmpl %ebp, %r14d
je 0x2f40
movl %r14d, %eax
movq 0x30(%rsp), %rcx
movq (%rcx,%rax,8), %rdi
callq 0x2220
movl %eax, %r13d
jmp 0x2afe
movq %rbx, %rdi
leaq 0x1746(%rip), %rsi      # 0x4182
callq 0x21f0
testl %eax, %eax
je 0x2a7f
cmpb $0x2d, %r15b
jne 0x29aa
cmpb $0x78, 0x1(%rbx)
jne 0x2a5f
cmpb $0x0, 0x2(%rbx)
je 0x2af4
cmpb $0x72, 0x1(%rbx)
jne 0x29aa
cmpb $0x0, 0x2(%rbx)
jne 0x29aa
movl $0xffffffff, 0x470f(%rip) # imm = 0xFFFFFFFF
jmp 0x2afe
movb $0x1, 0x4702(%rip)      # 0x7188
jmp 0x2afe
movl $0x1, %r12d
jmp 0x2afe
xorl %r12d, %r12d
jmp 0x2afe
movl $0x1, 0x20(%rsp)
jmp 0x2afe
movl $0x1, 0xc(%rsp)
jmp 0x2afe
incl %r14d
cmpl %ebp, %r14d
je 0x2f40
cmpl $0x2, 0x46d0(%rip)      # 0x718c
je 0x2f40
movl %r14d, %eax
movq 0x30(%rsp), %rcx
movq (%rcx,%rax,8), %rdi
xorl %esi, %esi
xorl %edx, %edx
callq 0x2050
movslq 0x46ae(%rip), %rcx      # 0x718c
leal 0x1(%rcx), %edx
movl %edx, 0x46a5(%rip)      # 0x718c
leaq 0x4662(%rip), %rdx      # 0x7150
movq %rax, (%rdx,%rcx,8)
jmp 0x2afe
movl $0x1, %eax
movq %rax, 0x28(%rsp)
incl %r14d
cmpl %ebp, %r14d
jb 0x2927
cmpl $0x0, 0x20(%rsp)
sete %r14b
cmpl $0x0, 0x28(%rsp)
sete %r15b
cmpl $0x0, 0xc(%rsp)
sete 0xc(%rsp)
cmpl $0x2, %r12d
jne 0x2f9a
movl $0x2, %r12d
jmp 0x2b43
movb $0x1, %r15b
movb $0x1, %r14b
movb $0x1, 0xc(%rsp)
movl 0x4643(%rip), %eax      # 0x718c
movl %eax, %ecx
orl %r12d, %ecx
setne %cl
cmpl $-0x1, %eax
setne %dl
testb %cl, %dl
jne 0x2ba7
leaq 0x1666(%rip), %rdi      # 0x41c8
leaq 0x1631(%rip), %rsi      # 0x419a
callq 0x2190
testq %rax, %rax
je 0x2fe0
movq %rax, %rbx
leaq 0x45cf(%rip), %rdi      # 0x7150
movl $0x10, %esi
movl $0x1, %edx
movq %rax, %rcx
callq 0x2210
cmpq $0x1, %rax
jne 0x2fe9
movq %rbx, %rdi
callq 0x2150
jmp 0x2bc4
cmpl $0x1, %eax
jne 0x2bc4
movabsq $0x6385a7c9eb0d2f41, %rax # imm = 0x6385A7C9EB0D2F41
xorq 0x4593(%rip), %rax      # 0x7150
movq %rax, 0x4594(%rip)      # 0x7158
testl %r13d, %r13d
je 0x2d28
leal 0x1(%r13), %eax
movslq %eax, %rdi
callq 0x21d0
movq %rax, 0x10(%rsp)
movslq %r13d, %rdx
movq 0x43f8(%rip), %rcx      # 0x6fe0
movq (%rcx), %rcx
movl $0x1, %esi
movq %rax, %rdi
movq %rdx, 0x20(%rsp)
callq 0x2210
testq %rax, %rax
jle 0x2e8d
leaq 0x40(%rsp), %r15
xorl %r13d, %r13d
testl %r12d, %r12d
je 0x2c4a
movl %r13d, %ebx
movl %r12d, %ebp
movq %r15, %r12
movl %r14d, %r15d
movb 0x4562(%rip), %r14b     # 0x7188
movq 0x10(%rsp), %rdi
movq 0x451e(%rip), %rdx      # 0x7150
testb %r14b, %r14b
je 0x2c67
movl 0x451b(%rip), %ecx      # 0x7158
movq %rax, %rsi
callq 0x31bd
movl %eax, %r13d
jmp 0x2c79
testb %r14b, %r14b
je 0x2cdb
movq 0x10(%rsp), %rsi
leaq 0x60(%rsp), %rdi
movq %rax, %rdx
callq 0x2472
jmp 0x2caf
movq 0x44ea(%rip), %rcx      # 0x7158
movq %rax, %rsi
callq 0x3057
movq %rax, %r13
cmpb $0x0, 0x1c(%rsp)
je 0x2ca0
xorb $0x1, %r14b
movzbl %r14b, %eax
leal 0x8(,%rax,8), %esi
leaq 0x153f(%rip), %rdi      # 0x41d5
movq %r13, %rdx
xorl %eax, %eax
callq 0x2030
addl %r13d, %ebx
movl %ebx, %r13d
movl %r15d, %r14d
movq %r12, %r15
movl %ebp, %r12d
movq 0x10(%rsp), %rdi
movq 0x4325(%rip), %rax      # 0x6fe0
movq (%rax), %rcx
movl $0x1, %esi
movq 0x20(%rsp), %rdx
callq 0x2210
testq %rax, %rax
jg 0x2c0e
jmp 0x2e90
movq 0x10(%rsp), %rsi
leaq 0x50(%rsp), %rcx
movq %rcx, 0x40(%rsp)
addq %rsi, %rax
movq %r15, %rdi
movq %rax, %rdx
callq 0x3642
leaq 0x80(%rsp), %rdi
movq %rdi, 0x38(%rsp)
movq %r15, %rsi
leaq 0x38(%rsp), %rdx
callq 0x36d8
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rax
cmpq %rax, %rdi
je 0x2caf
callq 0x2140
jmp 0x2caf
xorl %ebp, %ebp
movq 0x42af(%rip), %rax      # 0x6fe0
movq (%rax), %rdx
leaq 0x10(%rsp), %rdi
leaq 0x78(%rsp), %rsi
callq 0x21b0
movq %rax, %r13
cmpq $-0x1, %rax
je 0x2e88
decq %r13
cmpb $0x0, 0x1c(%rsp)
je 0x2d6c
movq 0x10(%rsp), %rdi
movq %r13, %rsi
callq 0x2040
movq %rax, 0x20(%rsp)
testb %r15b, %r15b
jne 0x2d8b
testb $0x1, %r13b
jne 0x2fff
movq 0x10(%rsp), %rdi
movq %r13, %rsi
callq 0x25bc
sarq %r13
testl %r12d, %r12d
jne 0x2e02
testb %r14b, %r14b
je 0x2da9
movq 0x10(%rsp), %rsi
leaq 0x60(%rsp), %rdi
movq %r13, %rdx
callq 0x2472
jmp 0x2d2a
movq 0x10(%rsp), %rsi
leaq 0x50(%rsp), %rax
movq %rax, 0x40(%rsp)
addq %rsi, %r13
leaq 0x40(%rsp), %rbx
movq %rbx, %rdi
movq %r13, %rdx
callq 0x3642
leaq 0x80(%rsp), %rdi
movq %rdi, 0x38(%rsp)
movq %rbx, %rsi
leaq 0x38(%rsp), %rdx
callq 0x36d8
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rax
cmpq %rax, %rdi
je 0x2d2a
callq 0x2140
jmp 0x2d2a
movb %r14b, 0x28(%rsp)
movb 0x437a(%rip), %r14b     # 0x7188
movq 0x10(%rsp), %rdi
movq 0x4336(%rip), %rdx      # 0x7150
testb %r14b, %r14b
je 0x2e32
movl 0x4333(%rip), %ecx      # 0x7158
movq %r13, %rsi
callq 0x31bd
movl %eax, %r13d
jmp 0x2e44
movq 0x431f(%rip), %rcx      # 0x7158
movq %r13, %rsi
callq 0x3057
movq %rax, %r13
cmpb $0x0, 0x1c(%rsp)
je 0x2e7b
xorb $0x1, %r14b
movzbl %r14b, %eax
leal 0x8(,%rax,8), %esi
leaq 0x13b0(%rip), %rdi      # 0x4211
movq %r13, %rdx
movq 0x20(%rsp), %rbx
movq %rbx, %rcx
xorl %eax, %eax
callq 0x2030
movq %rbx, %rdi
callq 0x21a0
addl %r13d, %ebp
movb 0x28(%rsp), %r14b
jmp 0x2d2a
movl %ebp, %r13d
jmp 0x2e90
xorl %r13d, %r13d
testl %r12d, %r12d
je 0x2eb9
xorl %ebx, %ebx
cmpl $0x1, %r12d
jne 0x2f79
leaq 0x1373(%rip), %rdi      # 0x421b
xorl %ebx, %ebx
movl %r13d, %esi
xorl %eax, %eax
callq 0x2030
jmp 0x2f79
testb %r14b, %r14b
je 0x2ef9
movl 0x60(%rsp), %esi
testl %esi, %esi
je 0x2f40
leaq 0x1358(%rip), %rdi      # 0x4225
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x2030
cmpb $0x0, 0xc(%rsp)
jne 0x2f79
movzbl 0x42a0(%rip), %esi      # 0x7188
leaq 0x60(%rsp), %rdi
callq 0x260e
movl %eax, %ebx
jmp 0x2f79
movq 0x98(%rsp), %rsi
testq %rsi, %rsi
je 0x2f40
leaq 0x1329(%rip), %rdi      # 0x4236
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x2030
cmpb $0x0, 0xc(%rsp)
jne 0x2f79
movq 0x90(%rsp), %rbx
testq %rbx, %rbx
je 0x2fc2
movq 0x8(%rbx), %rdi
movq 0x10(%rbx), %rsi
callq 0x2568
movq (%rbx), %rbx
jmp 0x2f25
movq 0x30(%rsp), %r14
movq (%r14), %rsi
leaq 0x12f9(%rip), %rdi      # 0x4248
leaq 0x1342(%rip), %rdx      # 0x4298
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x2030
movq (%r14), %rcx
leaq 0x16bf(%rip), %rdi      # 0x4628
movq %rcx, %rsi
movq %rcx, %rdx
movq %rcx, %r8
xorl %eax, %eax
callq 0x2030
leaq 0x80(%rsp), %rdi
callq 0x33a2
movl %ebx, %eax
addq $0xb8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x403f(%rip), %rax      # 0x6fe0
movq (%rax), %rdi
leaq 0x41e5(%rip), %rsi      # 0x7190
movl $0x100000, %edx         # imm = 0x100000
callq 0x2080
movl $0x0, 0x1c(%rsp)
jmp 0x2b43
movl 0x41b8(%rip), %esi      # 0x7180
movl 0x41b6(%rip), %edx      # 0x7184
leaq 0x1102(%rip), %rdi      # 0x40d7
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x2030
jmp 0x2f79
leaq 0x11b6(%rip), %rdi      # 0x419d
jmp 0x2ff0
leaq 0x11bf(%rip), %rdi      # 0x41af
callq 0x2130
movl $0x1, %ebx
jmp 0x2f79
leaq 0x11d6(%rip), %rdi      # 0x41dc
leaq 0x11de(%rip), %rsi      # 0x41eb
leaq 0x11e6(%rip), %rcx      # 0x41fa
movl $0x84, %edx
callq 0x20d0
jmp 0x303f
jmp 0x3026
jmp 0x303f
jmp 0x303f
movq %rax, %rbx
movq 0x40(%rsp), %rdi
leaq 0x50(%rsp), %rax
cmpq %rax, %rdi
je 0x3042
callq 0x2140
jmp 0x3042
movq %rax, %rbx
leaq 0x80(%rsp), %rdi
callq 0x33a2
movq %rbx, %rdi
callq 0x2260