// File: /workspace/github_c_makefile_star2_O3/aokad[P]sequeeze/seqtk.c
// Function: stk_mergefa
int stk_mergefa(int argc, char *argv[])
{
	gzFile fp[2];
	kseq_t *seq[2];
	int i, l, c, is_intersect = 0, is_haploid = 0, qual = 0, is_mask = 0, is_randhet = 0;
	uint64_t cnt[5];
	while ((c = getopt(argc, argv, "himrq:")) >= 0) {
		switch (c) {
			case 'i': is_intersect = 1; break;
			case 'h': is_haploid = 1; break;
			case 'm': is_mask = 1; break;
			case 'r': is_randhet = 1; break;
			case 'q': qual = atoi(optarg); break;
		}
	}
	if (is_mask && is_intersect) {
		fprintf(stderr, "[%s] `-i' and `-h' cannot be applied at the same time.\n", __func__);
		return 1;
	}
	if (optind + 2 > argc) {
		fprintf(stderr, "\nUsage: seqtk mergefa [options] <in1.fa> <in2.fa>\n\n");
		fprintf(stderr, "Options: -q INT   quality threshold [0]\n");
		fprintf(stderr, "         -i       take intersection\n");
		fprintf(stderr, "         -m       convert to lowercase when one of the input base is N\n");
		fprintf(stderr, "         -r       pick a random allele from het\n");
		fprintf(stderr, "         -h       suppress hets in the input\n\n");
		return 1;
	}
	for (i = 0; i < 2; ++i) {
		fp[i] = strcmp(argv[optind+i], "-")? gzopen(argv[optind+i], "r") : gzdopen(fileno(stdin), "r");
		seq[i] = kseq_init(fp[i]);
	}
	if (fp[0] == 0 || fp[1] == 0) {
		fprintf(stderr, "[E::%s] failed to open the input file/stream.\n", __func__);
		return 1;
	}
	cnt[0] = cnt[1] = cnt[2] = cnt[3] = cnt[4] = 0;
	srand48(11);
	while (kseq_read(seq[0]) >= 0) {
		int min_l, c[2], b[2], is_upper;
		kseq_read(seq[1]);
		if (strcmp(seq[0]->name.s, seq[1]->name.s))
			fprintf(stderr, "[%s] Different sequence names: %s != %s\n", __func__, seq[0]->name.s, seq[1]->name.s);
		if (seq[0]->seq.l != seq[1]->seq.l)
			fprintf(stderr, "[%s] Unequal sequence length: %ld != %ld\n", __func__, seq[0]->seq.l, seq[1]->seq.l);
		min_l = seq[0]->seq.l < seq[1]->seq.l? seq[0]->seq.l : seq[1]->seq.l;
		printf(">%s", seq[0]->name.s);
		for (l = 0; l < min_l; ++l) {
			c[0] = seq[0]->seq.s[l]; c[1] = seq[1]->seq.s[l];
			if (seq[0]->qual.l && seq[0]->qual.s[l] - 33 < qual) c[0] = tolower(c[0]);
			if (seq[1]->qual.l && seq[1]->qual.s[l] - 33 < qual) c[1] = tolower(c[1]);
			if (is_intersect) is_upper = (isupper(c[0]) || isupper(c[1]))? 1 : 0;
			else if (is_mask) is_upper = (isupper(c[0]) || isupper(c[1]))? 1 : 0;
			else is_upper = (isupper(c[0]) && isupper(c[1]))? 1 : 0;
			c[0] = seq_nt16_table[c[0]]; c[1] = seq_nt16_table[c[1]];
			if (c[0] == 0) c[0] = 15;
			if (c[1] == 0) c[1] = 15;
			b[0] = bitcnt_table[c[0]];
			b[1] = bitcnt_table[c[1]];
			if (is_upper) {
				if (b[0] == 1 && b[1] == 1) {
					if (c[0] == c[1]) ++cnt[0];
					else ++cnt[1];
				} else if (b[0] == 1 && b[1] == 2) ++cnt[2];
				else if (b[0] == 2 && b[1] == 1) ++cnt[3];
				else if (b[0] == 2 && b[1] == 2) ++cnt[4];
			}
			if (is_haploid && (b[0] > 1 || b[1] > 1)) is_upper = 0;
			if (is_intersect) {
				c[0] = c[0] & c[1];
				if (c[0] == 0) is_upper = 0; // FIXME: is this a bug - c[0] cannot be 0!
			} else if (is_mask) {
				if (c[0] == 15 || c[1] == 15) is_upper = 0;
				c[0] &= c[1];
				if (c[0] == 0) is_upper = 0;
			} else if (is_randhet) {
				if (b[0] == 1 && b[1] == 1) { // two homs
					c[0] |= c[1];
				} else if (((b[0] == 1 && b[1] == 2) || (b[0] == 2 && b[1] == 1)) && (c[0]&c[1])) { // one hom, one het
					c[0] = (lrand48()&1)? (c[0] & c[1]) : (c[0] | c[1]);
				} else if (b[0] == 2 && b[1] == 2 && c[0] == c[1]) { // double hets
					if (lrand48()&1) {
						if (lrand48()&1) {
							for (i = 8; i >= 1; i >>= 1) // pick the "larger" allele
								if (c[0]&i) c[0] &= i;
						} else {
							for (i = 1; i <= 8; i <<= 1) // pick the "smaller" allele
								if (c[0]&i) c[0] &= i;
						}
					} // else set as het
				} else is_upper = 0;
			} else c[0] |= c[1];
			c[0] = seq_nt16_rev_table[c[0]];
			if (!is_upper) c[0] = tolower(c[0]);
			if (l%60 == 0) putchar('\n');
			putchar(c[0]);
		}
		putchar('\n');
	}
	fprintf(stderr, "[%s] (same,diff,hom-het,het-hom,het-het)=(%ld,%ld,%ld,%ld,%ld)\n", __func__, (long)cnt[0], (long)cnt[1], (long)cnt[2], (long)cnt[3], (long)cnt[4]);
	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x88, %rsp
movq %rsi, %r14
movl %edi, %ebp
leaq 0x6554(%rip), %rdx      # 0xb6ff
callq 0x2240
testl %eax, %eax
js 0x5272
movl $0x0, 0xc(%rsp)
leaq 0x6538(%rip), %r15      # 0xb6ff
leaq 0x5f02(%rip), %r12      # 0xb0d0
movl $0x0, 0x18(%rsp)
movl $0x0, 0x10(%rsp)
xorl %r13d, %r13d
xorl %ebx, %ebx
addl $-0x68, %eax
cmpl $0xa, %eax
ja 0x522a
movslq (%r12,%rax,4), %rax
addq %r12, %rax
jmpq *%rax
movl $0x1, 0x18(%rsp)
jmp 0x522a
movl $0x1, %r13d
jmp 0x522a
movl $0x1, 0xc(%rsp)
jmp 0x522a
movq 0xadc1(%rip), %rax      # 0xffd8
movq (%rax), %rdi
callq 0x2250
movl %eax, 0x10(%rsp)
jmp 0x522a
movl $0x1, %ebx
movl %ebp, %edi
movq %r14, %rsi
movq %r15, %rdx
callq 0x2240
testl %eax, %eax
jns 0x51e3
testl %r13d, %r13d
setne %al
cmpl $0x0, 0xc(%rsp)
setne %cl
cmpl $0x0, 0x18(%rsp)
sete 0xb(%rsp)
testl %ebx, %ebx
sete 0xa(%rsp)
movl %eax, 0x14(%rsp)
movl %ecx, 0xc(%rsp)
andb %cl, %al
cmpb $0x1, %al
jne 0x5294
callq 0x2659
jmp 0x5730
movl $0x0, 0xc(%rsp)
movb $0x1, 0xb(%rsp)
movl $0x0, 0x10(%rsp)
movl $0x0, 0x14(%rsp)
movb $0x1, 0xa(%rsp)
movq 0xad35(%rip), %rax      # 0xffd0
movl (%rax), %eax
addl $0x2, %eax
cmpl %ebp, %eax
jle 0x52ae
callq 0x25c6
jmp 0x5730
xorl %eax, %eax
leaq 0x60(%rsp), %r13
leaq 0x50(%rsp), %r12
movb $0x1, %bpl
leaq 0x80(%rsp), %r15
leaq 0x78(%rsp), %rbx
movq 0xacff(%rip), %rcx      # 0xffd0
movslq (%rcx), %rcx
cltq
addq %rcx, %rax
movq (%r14,%rax,8), %rdi
cmpb $0x2d, (%rdi)
jne 0x52e8
cmpb $0x0, 0x1(%rdi)
je 0x531c
leaq 0x5eb9(%rip), %rsi      # 0xb1a8
callq 0x2220
movq %rax, (%r13)
movq %rax, %rdi
callq 0x3edd
movq %rax, (%r12)
movl $0x1, %eax
movq %rbx, %r12
movq %r15, %r13
testb $0x1, %bpl
movl $0x0, %ebp
jne 0x52ca
jmp 0x533b
movq 0xaca5(%rip), %rax      # 0xffc8
movq (%rax), %rdi
callq 0x21b0
movl %eax, %edi
leaq 0x5e74(%rip), %rsi      # 0xb1a8
callq 0x20b0
jmp 0x52f4
cmpq $0x0, 0x60(%rsp)
je 0x572b
cmpq $0x0, 0x80(%rsp)
je 0x572b
movl $0xb, %edi
callq 0x2210
movq 0x50(%rsp), %r15
movq %r15, %rdi
callq 0x3f27
testl %eax, %eax
js 0x5747
movq 0x78(%rsp), %r14
movq $0x0, 0x20(%rsp)
movq $0x0, 0x30(%rsp)
movq $0x0, 0x38(%rsp)
movq $0x0, 0x40(%rsp)
movq $0x0, 0x28(%rsp)
movq %r14, %rdi
callq 0x3f27
movq 0x10(%r15), %rbx
movq 0x10(%r14), %r12
movq %rbx, %rdi
movq %r12, %rsi
callq 0x2170
testl %eax, %eax
jne 0x56d2
movq 0x30(%r15), %rbx
movq 0x30(%r14), %r8
cmpq %r8, %rbx
jne 0x56fc
movq %rbx, %rax
cmpq %rbx, %rax
cmovbq %rax, %rbx
movq 0x10(%r15), %rsi
leaq 0x60b4(%rip), %rdi      # 0xb4a4
xorl %eax, %eax
callq 0x20f0
testl %ebx, %ebx
jle 0x56b3
andl $0x7fffffff, %ebx       # imm = 0x7FFFFFFF
movq %rbx, 0x18(%rsp)
callq 0x2290
movq %rax, 0x70(%rsp)
xorl %r13d, %r13d
movq 0x40(%r15), %rax
movsbl (%rax,%r13), %ebx
movq 0x40(%r14), %rax
movsbl (%rax,%r13), %ebp
cmpq $0x0, 0x48(%r15)
je 0x544b
movq 0x58(%r15), %rax
movsbl (%rax,%r13), %eax
addl $-0x21, %eax
cmpl 0x10(%rsp), %eax
jge 0x544b
movl %ebx, %edi
callq 0x21c0
movl %eax, %ebx
cmpq $0x0, 0x48(%r14)
je 0x546d
movq 0x58(%r14), %rax
movsbl (%rax,%r13), %eax
addl $-0x21, %eax
cmpl 0x10(%rsp), %eax
jge 0x546d
movl %ebp, %edi
callq 0x21c0
movl %eax, %ebp
movq 0x70(%rsp), %rax
movq (%rax), %rsi
movslq %ebx, %rax
movzwl (%rsi,%rax,2), %edi
movslq %ebp, %rcx
cmpb $0x0, 0xc(%rsp)
jne 0x548d
cmpb $0x0, 0x14(%rsp)
je 0x5499
movw $0x1, %dx
btl $0x8, %edi
jb 0x54ab
jmp 0x54a3
btl $0x8, %edi
jb 0x54a3
xorl %edx, %edx
jmp 0x54ab
movzbl 0x1(%rsi,%rcx,2), %edx
andl $0x1, %edx
leaq 0xacbe(%rip), %rsi      # 0x10170
movzbl (%rax,%rsi), %ebx
movzbl (%rcx,%rsi), %ebp
testb %bl, %bl
movl $0xf, %eax
cmovel %eax, %ebx
movl $0xff, %ecx
andl %ecx, %ebx
testb %bpl, %bpl
cmovel %eax, %ebp
andl %ecx, %ebp
leaq 0xaec6(%rip), %rax      # 0x103a0
movl (%rax,%rbx,4), %ecx
movl (%rax,%rbp,4), %eax
testw %dx, %dx
je 0x553c
cmpl $0x1, %ecx
jne 0x54fb
cmpl $0x1, %eax
jne 0x54fb
cmpb %bpl, %bl
jne 0x551d
incq 0x30(%rsp)
jmp 0x553c
cmpl $0x1, %ecx
jne 0x550c
cmpl $0x2, %eax
jne 0x550c
incq 0x40(%rsp)
jmp 0x553c
cmpl $0x2, %ecx
jne 0x5524
cmpl $0x1, %eax
jne 0x5524
incq 0x28(%rsp)
jmp 0x553c
incq 0x38(%rsp)
jmp 0x553c
movl %ecx, %esi
xorl $0x2, %esi
movl %eax, %edi
xorl $0x2, %edi
xorl %r8d, %r8d
orl %esi, %edi
sete %r8b
addq %r8, 0x20(%rsp)
movzwl %dx, %edx
cmpl $0x2, %eax
movl %edx, %r12d
movl $0x0, %esi
cmovgel %esi, %r12d
cmpl $0x2, %ecx
cmovgel %esi, %r12d
cmpb $0x0, 0xb(%rsp)
cmovnel %edx, %r12d
cmpb $0x0, 0xc(%rsp)
je 0x556d
andl %ebx, %ebp
jne 0x55b4
xorl %ebx, %ebx
jmp 0x558d
cmpb $0x0, 0x14(%rsp)
je 0x55a1
xorl %eax, %eax
cmpl $0xf, %ebp
cmovel %eax, %r12d
cmpl $0xf, %ebx
cmovel %eax, %r12d
andl %ebx, %ebp
movl $0x0, %ebx
jne 0x55b4
movq 0xaddc(%rip), %rax      # 0x10370
movl %ebx, %ecx
movsbl (%rax,%rcx), %ebx
movq 0x18(%rsp), %r12
jmp 0x55cb
cmpb $0x0, 0xa(%rsp)
jne 0x55b2
cmpl $0x1, %ecx
jne 0x5607
cmpl $0x1, %eax
jne 0x5607
orl %ebx, %ebp
movq 0xadb5(%rip), %rax      # 0x10370
movl %ebp, %ecx
movsbl (%rax,%rcx), %ebx
testl %r12d, %r12d
movq 0x18(%rsp), %r12
jne 0x55d4
movl %ebx, %edi
callq 0x21c0
movl %eax, %ebx
imull $0xeeeeeeef, %r13d, %eax # imm = 0xEEEEEEEF
rorl $0x2, %eax
cmpl $0x4444444, %eax        # imm = 0x4444444
ja 0x55ef
movl $0xa, %edi
callq 0x2060
movl %ebx, %edi
callq 0x2060
incq %r13
cmpq %r12, %r13
jne 0x5417
jmp 0x56b3
movl %eax, %edx
xorl $0x1, %edx
movl %ecx, %esi
xorl $0x1, %esi
movl %eax, %edi
xorl $0x2, %edi
movl %ecx, %r8d
xorl $0x2, %r8d
orl %edx, %r8d
sete %dl
orl %esi, %edi
je 0x562b
testb %dl, %dl
je 0x564c
movl %ebp, %edx
andl %ebx, %edx
je 0x564c
movl %edx, 0x4c(%rsp)
callq 0x21f0
orl %ebx, %ebp
testb $0x1, %al
movl 0x4c(%rsp), %eax
cmovel %ebp, %eax
movl %eax, %ebp
jmp 0x55b4
cmpb %bpl, %bl
jne 0x558d
cmpl $0x2, %ecx
jne 0x558d
cmpl $0x2, %eax
jne 0x558d
callq 0x21f0
testb $0x1, %al
je 0x56ac
callq 0x21f0
testb $0x1, %al
jne 0x5690
movl $0x1, %eax
movl %ebx, %ecx
movl %eax, %ebx
andl %ecx, %ebx
cmovel %ecx, %ebx
addl %eax, %eax
cmpl $0x9, %eax
jl 0x567e
jmp 0x56ac
movl $0x8, %eax
movl $0x8, %ecx
movl %ebx, %edx
movl %eax, %ebx
andl %edx, %ebx
cmovel %edx, %ebx
shrl %ecx
cmpl $0x2, %eax
movl %ecx, %eax
jae 0x569a
movl %ebx, %ebp
jmp 0x55b4
movl $0xa, %edi
callq 0x2060
movq %r15, %rdi
callq 0x3f27
testl %eax, %eax
jns 0x53a7
jmp 0x5774
movq 0xa91f(%rip), %rax      # 0xfff8
movq (%rax), %rdi
leaq 0x6191(%rip), %rsi      # 0xb874
leaq 0x6054(%rip), %rdx      # 0xb73e
movq %rbx, %rcx
movq %r12, %r8
xorl %eax, %eax
callq 0x2190
jmp 0x53ca
movq 0xa8f5(%rip), %rax      # 0xfff8
movq (%rax), %rdi
leaq 0x6190(%rip), %rsi      # 0xb89d
leaq 0x602a(%rip), %rdx      # 0xb73e
movq %rbx, %rcx
xorl %eax, %eax
callq 0x2190
movq 0x30(%r15), %rax
movq 0x30(%r14), %rbx
jmp 0x53de
callq 0x25a7
movl $0x1, %eax
addq $0x88, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq $0x0, 0x28(%rsp)
movq $0x0, 0x40(%rsp)
movq $0x0, 0x38(%rsp)
movq $0x0, 0x30(%rsp)
movq $0x0, 0x20(%rsp)
movq 0xa87d(%rip), %rax      # 0xfff8
movq (%rax), %rdi
leaq 0x6142(%rip), %rsi      # 0xb8c7
leaq 0x5fb2(%rip), %rdx      # 0xb73e
movq 0x30(%rsp), %rcx
movq 0x38(%rsp), %r8
movq 0x40(%rsp), %r9
xorl %eax, %eax
pushq 0x20(%rsp)
pushq 0x30(%rsp)
callq 0x2190
addq $0x10, %rsp
xorl %eax, %eax
jmp 0x5735