// File: /workspace/github_c_makefile_star2_O2/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 $0x78, %rsp
movq %rsi, %r14
movl %edi, %ebp
movl $0x0, 0x8(%rsp)
movb $0x1, %al
movl %eax, 0x14(%rsp)
leaq 0x55d7(%rip), %r15      # 0x96ff
leaq 0x4fa1(%rip), %rbx      # 0x90d0
pushq $0x1
popq %r12
movq 0x9e9e(%rip), %r13      # 0xdfd8
movl $0x0, 0x10(%rsp)
movl $0x0, 0x18(%rsp)
movl $0x0, 0xc(%rsp)
movl %ebp, %edi
movq %r14, %rsi
movq %r15, %rdx
callq 0x2240
testl %eax, %eax
js 0x41a2
addl $-0x68, %eax
cmpl $0xa, %eax
ja 0x4152
movslq (%rbx,%rax,4), %rax
addq %rbx, %rax
jmpq *%rax
movl %r12d, 0x18(%rsp)
jmp 0x4152
movl $0x0, 0x14(%rsp)
jmp 0x4152
movl %r12d, 0x8(%rsp)
jmp 0x4152
movq (%r13), %rdi
callq 0x2250
movl %eax, 0x10(%rsp)
jmp 0x4152
movl %r12d, 0xc(%rsp)
jmp 0x4152
cmpl $0x0, 0x8(%rsp)
je 0x41d4
cmpl $0x0, 0xc(%rsp)
je 0x41d4
movq 0x9e41(%rip), %rax      # 0xdff8
movq (%rax), %rdi
leaq 0x5545(%rip), %rsi      # 0x9706
leaq 0x5576(%rip), %rdx      # 0x973e
xorl %eax, %eax
callq 0x2190
jmp 0x4270
movq 0x9df5(%rip), %rbx      # 0xdfd0
movl (%rbx), %eax
addl $0x2, %eax
cmpl %ebp, %eax
jle 0x4284
movq 0x9e09(%rip), %r14      # 0xdff8
movq (%r14), %rcx
leaq 0x5551(%rip), %rdi      # 0x974a
pushq $0x33
popq %rsi
pushq $0x1
popq %rbx
movq %rbx, %rdx
callq 0x2260
movq (%r14), %rcx
leaq 0x556d(%rip), %rdi      # 0x977e
pushq $0x28
popq %rsi
movq %rbx, %rdx
callq 0x2260
movq (%r14), %rcx
leaq 0x5581(%rip), %rdi      # 0x97a7
pushq $0x24
popq %rsi
movq %rbx, %rdx
callq 0x2260
movq (%r14), %rcx
leaq 0x5591(%rip), %rdi      # 0x97cc
pushq $0x47
popq %rsi
movq %rbx, %rdx
callq 0x2260
movq (%r14), %rcx
leaq 0x55c4(%rip), %rdi      # 0x9814
pushq $0x30
popq %rsi
movq %rbx, %rdx
callq 0x2260
movq (%r14), %rcx
leaq 0x55e0(%rip), %rdi      # 0x9845
pushq $0x2e
popq %rsi
movq %rbx, %rdx
callq 0x2260
pushq $0x1
popq %rbx
movl %ebx, %eax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
xorl %r12d, %r12d
movq 0x9d3a(%rip), %r13      # 0xdfc8
leaq 0x4f13(%rip), %r15      # 0x91a8
cmpq $0x2, %r12
je 0x42e4
movslq (%rbx), %rax
addq %r12, %rax
movq (%r14,%rax,8), %rdi
cmpb $0x2d, (%rdi)
jne 0x42b0
cmpb $0x0, 0x1(%rdi)
je 0x42cf
movq %r15, %rsi
callq 0x2220
movq %rax, 0x60(%rsp,%r12,8)
movq %rax, %rdi
callq 0x3102
movq %rax, 0x50(%rsp,%r12,8)
incq %r12
jmp 0x4295
movq (%r13), %rdi
callq 0x21b0
movl %eax, %edi
movq %r15, %rsi
callq 0x20b0
jmp 0x42b8
cmpq $0x0, 0x60(%rsp)
je 0x46a5
cmpq $0x0, 0x68(%rsp)
je 0x46a5
pushq $0xb
popq %rdi
callq 0x2210
movq 0x50(%rsp), %r14
movq 0x58(%rsp), %r15
movq $0x0, 0x28(%rsp)
movq $0x0, 0x40(%rsp)
movq $0x0, 0x38(%rsp)
movq $0x0, 0x30(%rsp)
movq $0x0, 0x20(%rsp)
movq %r14, %rdi
callq 0x312e
testl %eax, %eax
js 0x46bb
movq %r15, %rdi
callq 0x312e
movq 0x10(%r14), %rbx
movq 0x10(%r15), %r12
movq %rbx, %rdi
movq %r12, %rsi
callq 0x2170
testl %eax, %eax
jne 0x464c
movq 0x30(%r14), %r13
movq 0x30(%r15), %r8
cmpq %r8, %r13
jne 0x4676
movq %r13, %rax
cmpq %r13, %rax
cmovbq %rax, %r13
movq 0x10(%r14), %rsi
leaq 0x5110(%rip), %rdi      # 0x94a4
xorl %eax, %eax
callq 0x20f0
testl %r13d, %r13d
movl $0x0, %eax
cmovlel %eax, %r13d
xorl %r12d, %r12d
movq %r13, 0x48(%rsp)
cmpq %r13, %r12
je 0x463f
movq 0x40(%r14), %rax
movsbl (%rax,%r12), %ebp
movq 0x40(%r15), %rax
movsbl (%rax,%r12), %ebx
cmpq $0x0, 0x48(%r14)
je 0x43ec
movq 0x58(%r14), %rax
movsbl (%rax,%r12), %eax
addl $-0x21, %eax
cmpl 0x10(%rsp), %eax
jge 0x43ec
movl %ebp, %edi
callq 0x21c0
movl %eax, %ebp
cmpq $0x0, 0x48(%r15)
je 0x440e
movq 0x58(%r15), %rax
movsbl (%rax,%r12), %eax
addl $-0x21, %eax
cmpl 0x10(%rsp), %eax
jge 0x440e
movl %ebx, %edi
callq 0x21c0
movl %eax, %ebx
callq 0x2290
movq (%rax), %rsi
movslq %ebp, %rax
movzwl (%rsi,%rax,2), %edi
movslq %ebx, %rcx
cmpl $0x0, 0xc(%rsp)
jne 0x4432
cmpl $0x0, 0x8(%rsp)
je 0x44bb
movw $0x1, %dx
btl $0x8, %edi
jb 0x4444
movzbl 0x1(%rsi,%rcx,2), %edx
andl $0x1, %edx
leaq 0x9d25(%rip), %rsi      # 0xe170
movzbl (%rax,%rsi), %ebx
movzbl (%rcx,%rsi), %ebp
testb %bl, %bl
pushq $0xf
popq %rax
cmovel %eax, %ebx
movl $0xff, %ecx
andl %ecx, %ebx
testb %bpl, %bpl
cmovel %eax, %ebp
andl %ecx, %ebp
leaq 0x9f2f(%rip), %rax      # 0xe3a0
movl (%rax,%rbx,4), %ecx
movl (%rax,%rbp,4), %eax
testw %dx, %dx
je 0x44e4
cmpl $0x1, %ecx
jne 0x4492
cmpl $0x1, %eax
jne 0x4492
cmpb %bpl, %bl
jne 0x44b4
incq 0x30(%rsp)
jmp 0x44e4
cmpl $0x1, %ecx
jne 0x44a3
cmpl $0x2, %eax
jne 0x44a3
incq 0x40(%rsp)
jmp 0x44e4
cmpl $0x2, %ecx
jne 0x44cc
cmpl $0x1, %eax
jne 0x44cc
incq 0x28(%rsp)
jmp 0x44e4
incq 0x38(%rsp)
jmp 0x44e4
btl $0x8, %edi
jb 0x443c
xorl %edx, %edx
jmp 0x4444
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, %r13d
movl $0x0, %esi
cmovgel %esi, %r13d
cmpl $0x2, %ecx
cmovgel %esi, %r13d
cmpl $0x0, 0x18(%rsp)
cmovel %edx, %r13d
cmpl $0x0, 0xc(%rsp)
je 0x4515
andl %ebx, %ebp
jne 0x455c
xorl %ebx, %ebx
jmp 0x4535
cmpl $0x0, 0x8(%rsp)
je 0x4549
xorl %eax, %eax
cmpl $0xf, %ebp
cmovel %eax, %r13d
cmpl $0xf, %ebx
cmovel %eax, %r13d
andl %ebx, %ebp
movl $0x0, %ebx
jne 0x455c
movq 0x9e34(%rip), %rax      # 0xe370
movl %ebx, %ecx
movsbl (%rax,%rcx), %ebx
movq 0x48(%rsp), %r13
jmp 0x4573
testb $0x1, 0x14(%rsp)
jne 0x455a
cmpl $0x1, %ecx
jne 0x45a1
cmpl $0x1, %eax
jne 0x45a1
orl %ebx, %ebp
movq 0x9e0d(%rip), %rax      # 0xe370
movl %ebp, %ecx
movsbl (%rax,%rcx), %ebx
testl %r13d, %r13d
movq 0x48(%rsp), %r13
jne 0x457c
movl %ebx, %edi
callq 0x21c0
movl %eax, %ebx
movl %r12d, %eax
xorl %edx, %edx
pushq $0x3c
popq %rcx
divl %ecx
testl %edx, %edx
jne 0x4592
pushq $0xa
popq %rdi
callq 0x2060
movl %ebx, %edi
callq 0x2060
incq %r12
jmp 0x43af
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 0x45c5
testb %dl, %dl
je 0x45e6
movl %ebp, %edx
andl %ebx, %edx
je 0x45e6
movl %edx, 0x1c(%rsp)
callq 0x21f0
orl %ebx, %ebp
testb $0x1, %al
movl 0x1c(%rsp), %eax
cmovel %ebp, %eax
movl %eax, %ebp
jmp 0x455c
cmpb %bpl, %bl
jne 0x4535
cmpl $0x2, %ecx
jne 0x4535
cmpl $0x2, %eax
jne 0x4535
callq 0x21f0
testb $0x1, %al
jne 0x4611
movl %ebx, %ebp
jmp 0x455c
callq 0x21f0
testb $0x1, %al
jne 0x462d
pushq $0x1
popq %rax
cmpl $0x8, %eax
jg 0x460a
movl %eax, %ecx
andl %ebx, %ecx
cmovnel %ecx, %ebx
addl %eax, %eax
jmp 0x461d
pushq $0x8
popq %rax
testl %eax, %eax
je 0x460a
movl %eax, %ecx
andl %ebx, %ecx
cmovnel %ecx, %ebx
shrl %eax
jmp 0x4630
pushq $0xa
popq %rdi
callq 0x2060
jmp 0x433b
movq 0x99a5(%rip), %rax      # 0xdff8
movq (%rax), %rdi
leaq 0x5217(%rip), %rsi      # 0x9874
leaq 0x50da(%rip), %rdx      # 0x973e
movq %rbx, %rcx
movq %r12, %r8
xorl %eax, %eax
callq 0x2190
jmp 0x436e
movq 0x997b(%rip), %rax      # 0xdff8
movq (%rax), %rdi
leaq 0x5216(%rip), %rsi      # 0x989d
leaq 0x50b0(%rip), %rdx      # 0x973e
movq %r13, %rcx
xorl %eax, %eax
callq 0x2190
movq 0x30(%r14), %rax
movq 0x30(%r15), %r13
jmp 0x4382
movq 0x994c(%rip), %rax      # 0xdff8
movq (%rax), %rdi
leaq 0x4ceb(%rip), %rsi      # 0x93a1
jmp 0x41c1
movq 0x9936(%rip), %rax      # 0xdff8
movq (%rax), %rdi
leaq 0x51fb(%rip), %rsi      # 0x98c7
leaq 0x506b(%rip), %rdx      # 0x973e
xorl %ebx, %ebx
movq 0x30(%rsp), %rcx
movq 0x38(%rsp), %r8
movq 0x40(%rsp), %r9
xorl %eax, %eax
pushq 0x20(%rsp)
pushq 0x30(%rsp)
callq 0x2190
popq %rcx
popq %rdx
jmp 0x4273