// File: /workspace/github_cpp_makefile_star2_O2/tplinderoth[P]introDist/Dxyz.cpp
// Function: vcf2Dxyz(std::basic_ifstream<char, std::char_traits<char>>&, std::basic_ifstream<char, std::char_traits<char>>&, std::basic_ofstream<char, std::char_traits<char>>&, int, int, double, int)
int vcf2Dxyz (std::ifstream &poptab, std::ifstream &vcf, std::ofstream &outf, int winsize, int step, double minmaf, int infmt) {
		// set up population table map
		std::map <std::string, int> popmap;
		if (setPopTable(poptab, popmap) <= 0) {
			return -1;
		}

		// set up instream
		std::streambuf *inbuf = NULL;
		boost::iostreams::filtering_streambuf<boost::iostreams::input> zipbuf;
		zipbuf.push(boost::iostreams::gzip_decompressor());
		if (infmt == 0) {
			inbuf = vcf.rdbuf();
		}
		else if (infmt == 1) {
			zipbuf.push(vcf);
			inbuf = &zipbuf;
		} else if (infmt == 2) {
			inbuf = std::cin.rdbuf();
		}
		std::istream instream(inbuf);

		// set up outstream
		std::streambuf *outbuf = NULL;
		if (outf.is_open()) {
			outbuf = outf.rdbuf();
		} else {
			outbuf = std::cout.rdbuf();
		}
		std::ostream outstream(outbuf);

		// print header to output
		printHeader(outstream);

		// process VCF file
		std::string vcfline;

		// skip headers and set up vector to hold tokens
		while (getline(instream, vcfline)) {
			if (vcfline[0] != '#' || vcfline[1] != '#')
				break;
		}

		// find individual's positions in allele vector
		std::vector<int> source_idx; // this is the source pop index positions
		std::vector<int> sink_idx; // this is the sink pop index positions
		std::vector<int> outgroup_idx; // this is the outgroup index positions

		std::stringstream ss(vcfline);
		std::string tok;
		int idxpos [2];
		int c = -9;
		int c2 = 0;
		int pop;
		while (ss >> tok) {
			if (c >= 0) {
				if (popmap.find(tok) != popmap.end()) {
					pop = popmap.find(tok)->second;
					idxpos[0] = c2;
					idxpos[1] = c2+1;

					if (pop == 0) {
						source_idx.insert(source_idx.end(), idxpos, idxpos+2);
					} else if (pop == 1) {
						sink_idx.insert(sink_idx.end(), idxpos, idxpos+2);
					} else if (pop == 2) {
						outgroup_idx.insert(outgroup_idx.end(), idxpos, idxpos+2);
					} else {
						std::cerr << "Invalid population code: " << pop << "\n";
						return -1;
					}

				}
				c2 += 2;
			}
			++c;
		}
		unsigned int nind = c;
		int nfields = c+9;
		std::cerr << "Number of individuals in VCF: " << nind << "\n";

		// set up data structures to hold site information

		// matrix to hold Dxy values
		Matrix<double> dxy(winsize, 5); // 0:source-sink dxy, 1:source-out dxy, 2:position, 3:number sequences with data, 4: maf

		// vector to hold alleles
		std::vector<int> alleles;
		alleles.resize(nind*2);

		// loop through VCF sites
		int i = 0, j = 0;
		std::string seqid;
		std::string prevseq;
		int nsitedata; // tracks number of sites in a window with data
		double nseqdata_win; // tracks average number of sequences per site in a window with data
		double dxy_components [2]; // 0=Source-Sink Dxy, 1=Source-Outgroup Dxy
		double dxyz;
		double winstart = 0; // holds start position of last printed window
		while (getline(instream, vcfline)) {
		// assume vcf fields are [0]=CHROM, [1]=POS, [2]=ID, [3]=REF, [4]=ALT, [5]=QUAL, [6]=FILTER, [7]=INFO, [8]=FORMAT

			// parse site information
			ss.clear();
			ss.str(vcfline);
			ss >> seqid; // extract CHROM
			ss >> dxy(j,2); // extract POS
			i=2;
			while (ss >> tok) {
				if (i > 8) {
					// extract genotypes
					if(parseGenotype(tok, alleles) == alleles.end()) {
						return -1;
					}
				} else if (i == 8) {
					// ensure genotypes are present
					if (tok[0] != 'G' || tok[1] != 'T') {
						std::cerr << "No GT subfield for " << seqid << " " << dxy(j,2) << "\n";
						return -1;
					}
				}
				++i;
			}

			if (i < nfields) {
				std::cerr << "Input VCF appears truncated\n";
				return -1;
			}

			// calculate average number of pairwise differences for site
			dxyComponents(alleles, source_idx, sink_idx, outgroup_idx, dxy, j);
			++j;

			if (j == winsize || (!prevseq.empty() && prevseq != seqid)) {
				winstart=dxy(0,2);

				// calculate Dxyz window
				dxyz = calcDxyzWindow(dxy, dxy.nrow()-1, &nseqdata_win, &nsitedata, minmaf, dxy_components);

				// print window
				printWindow(outstream, dxyz, seqid, dxy(0,2), dxy(winsize-1,2), nseqdata_win, nsitedata, dxy_components);

				// slide dxy window
				j = slideWindow(dxy, winsize, step, j);
			}

			prevseq = seqid;
		}

		// process last window if necessary
		if (dxy(0,2) != winstart) {
			dxyz = calcDxyzWindow(dxy, j-1, &nseqdata_win, &nsitedata, minmaf, dxy_components);
			printWindow(outstream, dxyz, seqid, dxy(0,2), dxy(j-1,2), nseqdata_win, nsitedata, dxy_components);
		}

		return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x5a8, %rsp            # imm = 0x5A8
movl %r9d, %ebp
movsd %xmm0, 0x50(%rsp)
movl %r8d, %r12d
movq %rcx, 0x18(%rsp)
movq %rdx, %rbx
movq %rsi, %r14
leaq 0x170(%rsp), %rax
andl $0x0, (%rax)
andq $0x0, 0x8(%rax)
movq %rax, 0x10(%rax)
movq %rax, 0x18(%rax)
andq $0x0, 0x20(%rax)
leaq 0x168(%rsp), %rsi
callq 0x794f
testl %eax, %eax
jle 0x6cb4
leaq 0x198(%rsp), %r15
movq %r15, %rdi
callq 0x81c6
leaq 0x1f8(%rsp), %rdi
pushq $0xf
popq %rsi
movl $0x1000, %edx           # imm = 0x1000
callq 0x81e6
movq 0x1e0(%rsp), %rdi
leaq 0x1f8(%rsp), %rsi
pushq $-0x1
popq %rcx
movq %rcx, %rdx
callq 0xa128
leaq 0x1f8(%rsp), %rdi
callq 0x828e
cmpl $0x2, %ebp
je 0x6cd4
cmpl $0x1, %ebp
je 0x6cbc
testl %ebp, %ebp
jne 0x6cec
addq $0x10, %r14
movq %r14, %r15
jmp 0x6cef
pushq $-0x1
popq %rbp
jmp 0x7315
leaq 0x1d8(%rsp), %rdi
pushq $-0x1
popq %rcx
movq %r14, %rsi
movq %rcx, %rdx
callq 0x82b4
jmp 0x6cef
movq 0x102f5(%rip), %rax     # 0x16fd0
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
movq 0xe8(%rax,%rcx), %r15
jmp 0x6cef
xorl %r15d, %r15d
leaq 0x490(%rsp), %rdi
movq %r15, %rsi
callq 0x6620
leaq 0x70(%rbx), %rdi
callq 0x60c0
testb %al, %al
je 0x6d12
addq $0x8, %rbx
jmp 0x6d28
movq 0x1028f(%rip), %rax     # 0x16fa8
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
movq 0xe8(%rax,%rcx), %rbx
leaq 0x380(%rsp), %rdi
movq %rbx, %rsi
callq 0x6160
leaq 0x380(%rsp), %rdi
callq 0x7a6c
leaq 0x100(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq 0x490(%rsp), %rbx
leaq 0xf0(%rsp), %r14
movq %rbx, %rdi
movq %r14, %rsi
callq 0x6090
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x6d95
movq 0xf0(%rsp), %rax
cmpb $0x23, (%rax)
jne 0x6d95
cmpb $0x23, 0x1(%rax)
je 0x6d69
movl %r12d, 0x44(%rsp)
xorpd %xmm0, %xmm0
movapd %xmm0, 0xa0(%rsp)
andq $0x0, 0xb0(%rsp)
movapd %xmm0, 0x80(%rsp)
andq $0x0, 0x90(%rsp)
movapd %xmm0, 0x60(%rsp)
andq $0x0, 0x70(%rsp)
leaq 0x1f8(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
pushq $0x18
popq %rdx
callq 0x6530
leaq 0x158(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
xorl %r15d, %r15d
pushq $-0x9
popq %rbx
pushq $-0x12
popq %rbp
leaq 0x148(%rsp), %r14
leaq 0x168(%rsp), %r12
leaq 0x1f8(%rsp), %rdi
movq %r14, %rsi
callq 0x6400
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x6ef3
testl %ebx, %ebx
js 0x6ee9
movq %r12, %rdi
movq %r14, %rsi
callq 0xcc74
leaq 0x170(%rsp), %rcx
cmpq %rcx, %rax
je 0x6ee5
movq %r12, %rdi
movq %r14, %rsi
callq 0xcc74
movl 0x40(%rax), %r13d
movl %r15d, 0x4(%rsp)
leal 0x1(%r15), %eax
movl %eax, 0x8(%rsp)
cmpl $0x2, %r13d
je 0x6ecc
cmpl $0x1, %r13d
je 0x6eab
testl %r13d, %r13d
jne 0x7336
movq 0xa8(%rsp), %rsi
leaq 0xa0(%rsp), %rdi
leaq 0x4(%rsp), %rdx
leaq 0xc(%rsp), %rcx
callq 0x82c6
jmp 0x6ee5
movq 0x88(%rsp), %rsi
leaq 0x80(%rsp), %rdi
leaq 0x4(%rsp), %rdx
leaq 0xc(%rsp), %rcx
callq 0x82c6
jmp 0x6ee5
movq 0x68(%rsp), %rsi
leaq 0x60(%rsp), %rdi
leaq 0x4(%rsp), %rdx
leaq 0xc(%rsp), %rcx
callq 0x82c6
addl $0x2, %r15d
incl %ebx
addl $0x2, %ebp
jmp 0x6e13
movq 0x100ee(%rip), %rdi     # 0x16fe8
leaq 0x7506(%rip), %rsi      # 0xe407
callq 0x6320
movl %ebx, %esi
movq %rax, %rdi
callq 0x6250
leaq 0x7174(%rip), %rsi      # 0xe08b
movq %rax, %rdi
callq 0x6320
movslq 0x18(%rsp), %rsi
leaq 0x20(%rsp), %rdi
pushq $0x5
popq %rdx
callq 0x82e6
xorpd %xmm0, %xmm0
leaq 0x110(%rsp), %rdi
movapd %xmm0, (%rdi)
andq $0x0, 0x10(%rdi)
movl %ebp, %esi
callq 0x83d0
addl $0x9, %ebx
leaq 0xd0(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
xorl %r13d, %r13d
movb %r13b, (%rax)
leaq 0x138(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb %r13b, (%rax)
leaq 0x210(%rsp), %r15
movq 0x18(%rsp), %rax
decl %eax
movl %eax, 0x40(%rsp)
xorpd %xmm0, %xmm0
movsd %xmm0, 0x48(%rsp)
leaq 0x490(%rsp), %rdi
leaq 0xf0(%rsp), %r14
leaq 0x148(%rsp), %rbp
leaq 0x110(%rsp), %r12
movq %r14, %rsi
callq 0x6090
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x736b
movq 0x1f8(%rsp), %rax
movq -0x18(%rax), %rdi
leaq 0x1f8(%rsp), %rax
addq %rax, %rdi
xorl %esi, %esi
callq 0x6590
movq %r15, %rdi
movq %r14, %rsi
callq 0x64d0
leaq 0x1f8(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x6400
leaq 0x20(%rsp), %rdi
movl %r13d, %esi
pushq $0x2
popq %rdx
callq 0x8402
leaq 0x1f8(%rsp), %rdi
movq %rax, %rsi
callq 0x6240
pushq $0x2
popq %r15
leaq 0x1f8(%rsp), %rdi
movq %rbp, %rsi
callq 0x6400
movq (%rax), %rcx
movq -0x18(%rcx), %rcx
testb $0x5, 0x20(%rax,%rcx)
jne 0x709f
cmpl $0x9, %r15d
jb 0x7079
movq %rbp, %rdi
movq %r12, %rsi
callq 0x7a82
movq 0x10316(%rip), %rax     # 0x17380
cmpq 0x118(%rsp), %rax
jne 0x709a
jmp 0x720a
cmpl $0x8, %r15d
jne 0x709a
movq 0x148(%rsp), %rax
cmpb $0x47, (%rax)
jne 0x720f
cmpb $0x54, 0x1(%rax)
jne 0x720f
incl %r15d
jmp 0x7034
cmpl %ebx, %r15d
jl 0x743e
movq %r12, %rdi
leaq 0xa0(%rsp), %rsi
leaq 0x80(%rsp), %rdx
leaq 0x60(%rsp), %rcx
leaq 0x20(%rsp), %r14
movq %r14, %r8
movl %r13d, %r9d
callq 0x7b89
incl %r13d
cmpl 0x18(%rsp), %r13d
je 0x7106
cmpq $0x0, 0x130(%rsp)
je 0x71d8
leaq 0x128(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x8454
testb %al, %al
je 0x71d8
movq %r14, %rdi
xorl %esi, %esi
pushq $0x2
popq %rdx
callq 0x8402
movsd (%rax), %xmm0
movsd %xmm0, 0x48(%rsp)
movl 0x20(%rsp), %esi
decl %esi
movq %r14, %rdi
leaq 0x38(%rsp), %rdx
leaq 0x14(%rsp), %rcx
movsd 0x50(%rsp), %xmm0
leaq 0xe0(%rsp), %r8
callq 0x7dd9
movsd %xmm0, 0x58(%rsp)
movq %r14, %rdi
xorl %esi, %esi
pushq $0x2
popq %r15
movl %r15d, %edx
callq 0x8402
cvttsd2si (%rax), %rax
movl %eax, 0x10(%rsp)
movq %r14, %rdi
movl 0x40(%rsp), %esi
movl %r15d, %edx
callq 0x8402
cvttsd2si (%rax), %rax
movl %eax, 0xc(%rsp)
cvtsi2sdl 0x14(%rsp), %xmm0
movsd %xmm0, 0x30(%rsp)
leaq 0x380(%rsp), %rdi
leaq 0x58(%rsp), %rsi
leaq 0xc0(%rsp), %rdx
leaq 0x10(%rsp), %rcx
leaq 0xc(%rsp), %r8
leaq 0x38(%rsp), %r9
leaq 0xe0(%rsp), %rax
pushq %rax
leaq 0x38(%rsp), %rax
pushq %rax
callq 0x7f26
popq %rax
popq %rcx
movq %r14, %rdi
movq 0x18(%rsp), %rsi
movl 0x44(%rsp), %edx
movl %r13d, %ecx
callq 0x804c
movl %eax, %r13d
leaq 0x210(%rsp), %r15
leaq 0x128(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x61f0
leaq 0x490(%rsp), %rdi
leaq 0xf0(%rsp), %r14
jmp 0x6fb8
pushq $-0x1
popq %rbp
jmp 0x7272
movq 0xfdd2(%rip), %rdi      # 0x16fe8
leaq 0x7209(%rip), %rsi      # 0xe426
callq 0x6320
pushq $-0x1
popq %rbp
leaq 0xc0(%rsp), %rsi
movq %rax, %rdi
callq 0x62e0
leaq 0x71e8(%rip), %rsi      # 0xe424
movq %rax, %rdi
callq 0x6320
movq %rax, %rbx
leaq 0x20(%rsp), %rdi
pushq $0x2
popq %rdx
movl %r13d, %esi
callq 0x8402
movsd (%rax), %xmm0
movq %rbx, %rdi
callq 0x6540
movq %rax, %rdi
leaq 0x6e1e(%rip), %rsi      # 0xe08b
callq 0x6320
leaq 0x128(%rsp), %rdi
callq 0x61a0
leaq 0xc0(%rsp), %rdi
callq 0x61a0
leaq 0x110(%rsp), %rdi
callq 0xcc40
leaq 0x20(%rsp), %rdi
callq 0x845e
leaq 0x148(%rsp), %rdi
callq 0x61a0
leaq 0x1f8(%rsp), %rdi
callq 0x6290
leaq 0x60(%rsp), %rdi
callq 0xcc40
leaq 0x80(%rsp), %rdi
callq 0xcc40
leaq 0xa0(%rsp), %rdi
callq 0xcc40
leaq 0xf0(%rsp), %rdi
callq 0x61a0
leaq 0x388(%rsp), %rdi
callq 0x6110
leaq 0x490(%rsp), %rdi
callq 0x6580
leaq 0x198(%rsp), %rdi
callq 0x849e
leaq 0x168(%rsp), %rdi
callq 0x858c
movl %ebp, %eax
addq $0x5a8, %rsp            # imm = 0x5A8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0xfcab(%rip), %rdi      # 0x16fe8
leaq 0x70a9(%rip), %rsi      # 0xe3ed
callq 0x6320
movq %rax, %rdi
movl %r13d, %esi
callq 0x65c0
leaq 0x6d30(%rip), %rsi      # 0xe08b
movq %rax, %rdi
callq 0x6320
pushq $-0x1
popq %rbp
jmp 0x72a3
leaq 0x20(%rsp), %rdi
xorl %ebp, %ebp
pushq $0x2
popq %rdx
xorl %esi, %esi
callq 0x8402
movsd (%rax), %xmm0
ucomisd 0x48(%rsp), %xmm0
jne 0x738e
jnp 0x7272
decl %r13d
leaq 0x20(%rsp), %r12
leaq 0x38(%rsp), %rdx
leaq 0x14(%rsp), %r14
movq %r12, %rdi
movl %r13d, %esi
movq %r14, %rcx
movsd 0x50(%rsp), %xmm0
leaq 0xe0(%rsp), %r8
callq 0x7dd9
leaq 0x58(%rsp), %r15
movsd %xmm0, (%r15)
pushq $0x2
popq %rbp
movq %r12, %rdi
xorl %esi, %esi
movl %ebp, %edx
callq 0x8402
cvttsd2si (%rax), %rax
leaq 0x10(%rsp), %rbx
movl %eax, (%rbx)
movq %r12, %rdi
movl %r13d, %esi
movl %ebp, %edx
callq 0x8402
cvttsd2si (%rax), %rax
leaq 0xc(%rsp), %r8
movl %eax, (%r8)
cvtsi2sdl (%r14), %xmm0
movsd %xmm0, 0x30(%rsp)
leaq 0x380(%rsp), %rdi
leaq 0xc0(%rsp), %rdx
movq %r15, %rsi
movq %rbx, %rcx
leaq 0x38(%rsp), %r9
leaq 0xe0(%rsp), %rax
pushq %rax
leaq 0x38(%rsp), %rax
pushq %rax
callq 0x7f26
popq %rax
popq %rcx
xorl %ebp, %ebp
jmp 0x7272
leaq 0x6ff5(%rip), %rsi      # 0xe43a
pushq $-0x1
popq %rbp
movq 0xfb99(%rip), %rdi      # 0x16fe8
jmp 0x726d
jmp 0x74be
jmp 0x7492
jmp 0x74b9
jmp 0x74be
movq %rax, %rbx
jmp 0x74db
jmp 0x74b9
movq %rax, %rbx
jmp 0x750c
movq %rax, %rbx
jmp 0x753d
movq %rax, %rbx
jmp 0x754a
jmp 0x7492
movq %rax, %rbx
leaq 0x1f8(%rsp), %rdi
callq 0x828e
jmp 0x7557
movq %rax, %rbx
jmp 0x7557
jmp 0x749c
movq %rax, %rbx
jmp 0x7564
jmp 0x74be
jmp 0x74b9
jmp 0x74b9
jmp 0x74b9
jmp 0x74b9
jmp 0x74be
jmp 0x74b9
movq %rax, %rbx
jmp 0x7530
jmp 0x74b9
movq %rax, %rbx
jmp 0x74f2
movq %rax, %rbx
leaq 0x128(%rsp), %rdi
callq 0x61a0
leaq 0xc0(%rsp), %rdi
callq 0x61a0
leaq 0x110(%rsp), %rdi
callq 0xcc40
leaq 0x20(%rsp), %rdi
callq 0x845e
leaq 0x148(%rsp), %rdi
callq 0x61a0
leaq 0x1f8(%rsp), %rdi
callq 0x6290
leaq 0x60(%rsp), %rdi
callq 0xcc40
leaq 0x80(%rsp), %rdi
callq 0xcc40
leaq 0xa0(%rsp), %rdi
callq 0xcc40
leaq 0xf0(%rsp), %rdi
callq 0x61a0
leaq 0x388(%rsp), %rdi
callq 0x6110
leaq 0x490(%rsp), %rdi
callq 0x6580
leaq 0x198(%rsp), %rdi
callq 0x849e
leaq 0x168(%rsp), %rdi
callq 0x858c
movq %rbx, %rdi
callq 0x65d0