// File: /workspace/github_cpp_makefile_star2_O2/lrq3000[P]rfrb/./src/fileHandler.cpp
// Function: FileHandler::estimateStripeMap(bool)
std::vector<std::vector<mapEntry>> FileHandler::estimateStripeMap(bool isRaid5)
{
	//Lambda function, which is done by threads
	auto lambda = [&] (size_t id) -> std::vector<Block>
	{
		//Initialization
		std::vector<Block> blocks;
		FileReader *me = inFiles.at(id);
		const size_t CHECKS = 400;
		me->reset();
		const int checkSize=1;
		bool checkGapSize = false;
		size_t startBlock=0,endBlock=0;
		bool zeroStart=false, zeroEnd=false;
		size_t blockSize = mStripeSize;
		size_t gap = mStripeSize - (checkSize * me->getBlockSize());
		gap -= (checkSize * me->getBlockSize());
		Block pushMe;
		size_t outputCounter = 0;
		while (true)
		{
			//Output
			if (outputCounter == 0)
			{
				std::string wr = "Thread ";
				wr += std::to_string(id);
				wr += " working \t";
				wr += me->getRelativePos();
				printf("\r%s\t%6lu",wr.c_str(), blocks.size());
				fflush(stdout);
			}
			outputCounter = (outputCounter + 1) % 25000;
			if (blocks.size() > CHECKS)
				break;

			//Error
			if (me->findFirstNonemptyBlock() == -1)
			{
				break;
			}

			//Get adress and check the gap
			size_t adress = me->getCurrentAdress();
			if (checkGapSize == true)
			{
				size_t tmp = adress;
				if (tmp >= endBlock-checkSize*me->getBlockSize())
				{
					pushMe.zeroFirst = zeroStart;
					pushMe.zeroLast = zeroEnd;
					pushMe.startAdress = startBlock/blockSize;
					pushMe.endAdress = endBlock/blockSize;
					blocks.push_back(pushMe);
					startBlock = adress;
				}
				if (startBlock % blockSize != 0)
				{
					startBlock -= me->getBlockSize();
					zeroStart=true;
				}
				else
				{
					zeroStart=false;
				}
			}
			else
			{
				startBlock = adress;
				if (startBlock % blockSize != 0)
				{
					startBlock -= me->getBlockSize();
					zeroStart=true;
				}
				else
				{
					zeroStart=false;
				}
			}

			//Calculate entropy and check if it's relevant
			pushMe.entropies.clear();
			pushMe.entropies.push_back(me->calcEntropyOfCurrentBlock());
			while (me->newBlock()==true)
			{
				//Output
				if (outputCounter == 0)
				{
					std::string wr = "Thread ";
					wr += std::to_string(id);
					wr += " working \t";
					wr += me->getRelativePos();
					printf("\r%s\t%6lu",wr.c_str(), blocks.size());
					fflush(stdout);
				}
				outputCounter = (outputCounter + 1) % 25000;
				if (blocks.size() > CHECKS)
					break;
				float f = me->calcEntropyOfCurrentBlock();
				if (f == 0.0f)
					break;
				pushMe.entropies.push_back(f);
			}

			endBlock = me->getCurrentAdress();
			if (endBlock % blockSize != 0)
			{
				endBlock += me->getBlockSize();
				zeroEnd=true;
			}
			else
			{
				zeroEnd=false;
			}
			if (endBlock - startBlock < checkSize*me->getBlockSize())
			{
				checkGapSize = false;
			}
			else
			{
				checkGapSize = true;
			}
		}
		me->reset();
		return blocks;
	}; //lambda function end

	//Initialization to start threads
	unsigned int NUM_THREADS = inFiles.size();
	std::vector<std::pair<size_t, float>> entropies;
	std::vector<std::future<std::vector<Block>>> futureResults(inFiles.size());
	std::vector<std::vector<Block>> results(inFiles.size());
	for (size_t i = 0; i < NUM_THREADS; ++i)
	{
		inFiles.at(i)->setBlockSize(mStripeSize);
		futureResults[i] = std::async(std::launch::async, lambda, i);
	}
	for (size_t i = 0; i < NUM_THREADS; ++i)
	{
		results.at(i) = futureResults.at(i).get();
		inFiles.at(i)->setBlockSize(mStripeSize);
	}
	std::cout << std::endl;
	std::cout << "\tEntropie calculation finished" << std::endl;

	std::vector<std::vector<std::pair<bool, std::vector<size_t>>>> map;
	map.resize(results.size());

	//Build the heuristic with the modulo operation and the block begins and ends
	std::vector<size_t> parityDist;
	std::vector<std::vector<std::pair<bool, std::vector<size_t>>>> entropyMat = buildMapHeuristic(results, parityDist);

	//Initializing the resulting stripingMap
	std::vector<std::vector<mapEntry>> stripingMap;
	std::vector<std::pair<size_t, size_t>> referenceCounters;
	std::pair<size_t,size_t> c;
	size_t revC = results.size()-2;
	if (isRaid5==false)
		revC++;
	for (size_t i = 0; i < results.size(); ++i)
	{
		referenceCounters.push_back(std::pair<size_t,size_t>(0,revC));
	}
	for (size_t j = 0; j < results.size(); ++j)
	{
		std::vector<mapEntry> b;
		for (size_t i = 0; i < results.size(); ++i)
		{
			if (isRaid5 == true)
			{
				if (parityDist.at(j) == i)
				{
					b.push_back(mapEntry(true,-2));
				}
				else
				{
					b.push_back(mapEntry(false, -1));
				}
			}
			else
			{
				b.push_back(mapEntry(false, -1));
			}
		}
		stripingMap.push_back(b);
		if (isRaid5==false)
			break;

	}

	std::vector<size_t> posValues;
	if (isRaid5 == true)
	{
		posValues = std::vector<size_t>(results.size(), results.size()-1);
	}
	else
	{
		posValues = std::vector<size_t>(1, results.size());
	}

	//Sort, if it is Raid0 for the later algorithm
	if (isRaid5 == false)
	{
		for (size_t i = 1; i < entropyMat.size();)
		{
			for (size_t j = 0; j < entropyMat.at(i).size(); ++j)
			{
				entropyMat.at(0).push_back(entropyMat.at(i).at(j));
			}
			entropyMat.erase(entropyMat.begin()+i);
		}
	}

	//*
	// * DEBUG OUTPUT - do not delete me
	// *
/*	std::cout << std::endl;
	for (auto in : entropyMat)
	{
		std::cout << "Begin" << std::endl;
		for (auto in2 : in)
		{
			if (in2.first == true)
			{
				for (auto in3 : in2.second)
				{
					std::cout << in3 << ";";
				}
				std::cout << " ";
			}
		}
		std::cout << std::endl;
		std::cout << "End" << std::endl;
		for (auto in2 : in)
		{
			if (in2.first == false)
			{
				for (auto in3 : in2.second)
				{
					std::cout << in3 << ";";
				}
				std::cout << " ";
			}
		}
		std::cout << std::endl;
	}
	std::cout << std::endl;
*/

	float probability = 1.0f;
	//left = 1, right = 2
	int leftRight = 0;
	//asymm = 1, symm = 2
	int asymm_symm = 0;

	//In this loop we determine the striping map out of the map heuristic, we built earlier
	while (probability > 0.5f)
	{
		size_t entropyMatRunner=0;
		//*
		// * DEBUG OUTPUT - do not delete me
		// *
/*		for (auto &in : stripingMap)
		{
			std::cout << std::setw(10) << " ";
			for (auto &it : in)
			{
				if (it.isParity)
				{
					std::cout << std::setw(4) << "P";
				}
				else
				{
					std::cout << std::setw(4) << std::to_string(it.dataBlock);
				}
			}
			std::cout << std::endl;
		}
		std::cout << std::endl << std::endl;
		std::cout << std::to_string(probability) << std::endl;
*/		//Debug output -end

		size_t lineC=0;
		for (auto &in : entropyMat)
		{
			//We have to rerun each vec at least all images times
			//Possible-vec is size of all images, each entry representing one image
			//pair.first for begin-block, pair.second for end-block
			std::vector<std::pair<size_t, size_t>> possible(results.size(), std::pair<size_t,size_t>(0,0));
			std::pair<size_t, size_t> occCounter(0,0);
			for (auto &moduloEntry : in)
			{
				if (moduloEntry.second.size()>0)
				{
					if (moduloEntry.first == true)
					{
						++occCounter.first;
					}
					else
					{
						++occCounter.second;
					}
				}
				for (auto &modVecEntry : moduloEntry.second)
				{
					if (moduloEntry.first == true)
					{
						++possible.at(modVecEntry).first;
					}
					else
					{
						++possible.at(modVecEntry).second;
					}
				}
			}

			//Check if the probability is high enough to determine the entry
			for (size_t entry = 0; entry < results.size(); ++entry)
			{
				short begin=-1;
				if (possible.at(entry).first == 0 && possible.at(entry).second == 0)
					continue;
				if (occCounter.second > occCounter.first)
				{
					if ((float)possible.at(entry).second/(float)occCounter.second >= probability)
					{
						begin = 0;
					}
				}
				else if (begin == -1 && occCounter.first>0)
				{
					if ((float)possible.at(entry).first/(float)occCounter.first >= probability)
					{
						begin = 1;
					}
				}
				if (begin != -1)
				{
					//We found something
					possible.at(entry).first = 0;
					possible.at(entry).second = 0;
					stripingMap.at(entropyMatRunner).at(entry).isParity = false;
					if (begin == 1)
					{
						stripingMap.at(entropyMatRunner).at(entry).dataBlock = referenceCounters.at(entropyMatRunner).first++;
					}
					else
					{
						stripingMap.at(entropyMatRunner).at(entry).dataBlock = referenceCounters.at(entropyMatRunner).second--;
					}
					--posValues.at(entropyMatRunner);

					//Evrything fine, kill each entry in line because we found an entry
					for (auto &moduloEntry : in)
					{
						if (posValues.at(entropyMatRunner) == 0)
						{
							moduloEntry.second.clear();
						}
						for (size_t burn = 0; burn < moduloEntry.second.size();)
						{
							if (moduloEntry.second.at(burn) == entry)
							{
								moduloEntry.second.erase(moduloEntry.second.begin()+burn);
							}
							else
							{
								++burn;
							}
						}
					}
					probability = 1.0f;
					break;
				}
			}
			if (posValues.at(entropyMatRunner) == 1)
			{
				for (size_t i = 0; i < stripingMap.at(entropyMatRunner).size(); ++i)
				{
					if (stripingMap.at(entropyMatRunner).at(i).dataBlock == -1)
					{
						stripingMap.at(entropyMatRunner).at(i).dataBlock = referenceCounters.at(entropyMatRunner).first++;
						posValues.at(entropyMatRunner) = 0;
						for (auto &moduloEntry : in)
							moduloEntry.second.clear();
						break;
					}
				}
			}
			++lineC;
			++entropyMatRunner;
		}
		probability -= 0.05f;

		//Another approach, only for Raid5; Depends on left-right and symm-asymm builds
		if (isRaid5 == true)
		{
			int curNum = -1;
			for (size_t i = 1; i < stripingMap.size(); ++i)
			{
				for (size_t j = 0; j < stripingMap.at(i).size(); ++j)
				{
					if (stripingMap.at(i).at(j).isParity == true)
					{
						//Get upper datablocknum
						int tmp = stripingMap.at(i-1).at(j).dataBlock;
						if (tmp != -1)
						{
							if (curNum == -1)
							{
								curNum = tmp;
							}
							else //we found a block
							{
								if (tmp > curNum)
								{
									asymm_symm = 1;
									leftRight = 2;
								}
								else if (tmp < curNum)
								{
									asymm_symm = 1;
									leftRight = 1;
								}
								else
								{
									asymm_symm = 2;
									if (tmp == 0)
									{
										leftRight = 2;
									}
									else if (tmp == (int)(inFiles.size()-1))
									{
										leftRight = 1;
									}
									else
									{
										std::cerr << "Error in stripingMap building algorithm" << std::endl;
										return std::vector<std::vector<mapEntry>>();
									}
								}
							}
						}
					}
				}
			}
		}
		if (leftRight != 0 && asymm_symm != 0)
			break;
	}

	//Error, should not happen
	if (leftRight == 0 && asymm_symm == 0 && isRaid5 == true)
	{
		std::cerr << "Couldnt determine stripemap type" << std::endl;
		return std::vector<std::vector<mapEntry>>();
	}

	//Build resulting Stripemap from the found information
	if (isRaid5 == true)
	{
		std::vector<size_t> order;
		if (leftRight == 2)
		{
			for (size_t i = 0; i < parityDist.size(); ++i)
			{
				order.push_back(parityDist.at(i));
			}
		}
		else
		{
			for (size_t i = 0; i < parityDist.size(); ++i)
			{
				order.push_back(parityDist.at(parityDist.size()-(i+1)));
			}
		}

		//Fill the stripemap
		for (size_t i = 0; i < stripingMap.size(); ++i)
		{
			size_t counter;
			if (asymm_symm == 1)
			{
				counter = 0;
			}
			else
			{
				if (leftRight == 1)
				{
					counter = i;
				}
				else
				{
					counter = inFiles.size()-(i-1);
				}
			}
			for (size_t j = 0; j < stripingMap.at(i).size(); ++j)
			{
				if (stripingMap.at(i).at(order.at(j)).isParity == false)
				{
					stripingMap.at(i).at(order.at(j)).dataBlock = counter;
					counter = (counter+1)%(inFiles.size()-1);
				}
			}
		}
	}
	//Else, ask user
	userStripeMapInteraction(stripingMap);
	return stripingMap;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x198, %rsp            # imm = 0x198
movl %edx, 0xc(%rsp)
movq %rsi, %r14
movq %rdi, 0xe8(%rsp)
movq 0x48(%rsi), %rbx
subq 0x40(%rsi), %rbx
sarq $0x3, %rbx
xorps %xmm0, %xmm0
movaps %xmm0, 0x180(%rsp)
andq $0x0, 0x190(%rsp)
leaq 0x168(%rsp), %rdi
leaq 0x68(%rsp), %rdx
movq %rbx, %rsi
callq 0xbae8
movq 0x48(%r14), %rsi
subq 0x40(%r14), %rsi
sarq $0x3, %rsi
leaq 0x68(%rsp), %rdi
leaq 0xc0(%rsp), %rdx
callq 0xbb3a
movq 0xe8(%rsp), %rax
movq %rax, 0x158(%rsp)
movq %r14, 0x10(%rsp)
leaq 0x40(%r14), %rbp
movl %ebx, %eax
movq %rax, 0x18(%rsp)
xorl %r14d, %r14d
leaq 0x30(%rsp), %r15
xorl %ebx, %ebx
movq %r14, 0x28(%rsp)
cmpq %rbx, 0x18(%rsp)
je 0x8887
movq %rbp, %rdi
movq %rbx, %rsi
callq 0x6f22
movq (%rax), %rdi
movq 0x10(%rsp), %rax
movq 0x60(%rax), %rsi
callq 0xf644
movq %r15, %r14
movq %rbp, %r13
xorps %xmm0, %xmm0
movaps %xmm0, 0xa0(%rsp)
pushq $0x58
popq %rdi
callq 0x5390
movq %rax, %r12
leaq 0x80(%rsp), %rax
movq %rax, 0xc0(%rsp)
movabsq $0x100000001, %rax      # imm = 0x100000001
movq %rax, 0x8(%r12)
leaq 0x1512d(%rip), %rax     # 0x1d730
movq %rax, (%r12)
andq $0x0, 0x18(%r12)
movq %r12, 0xc8(%rsp)
andl $0x0, 0x20(%r12)
movb $0x0, 0x24(%r12)
andl $0x0, 0x28(%r12)
leaq 0x10(%r12), %rbp
andq $0x0, 0x30(%r12)
andl $0x0, 0x38(%r12)
leaq 0x15141(%rip), %rax     # 0x1d780
movq %rax, 0x10(%r12)
pushq $0x30
popq %rdi
callq 0x5390
movq %rax, %r15
movq %rax, %rdi
callq 0xd8be
movq %r15, 0x40(%r12)
movq %rbx, 0x48(%r12)
movq 0x10(%rsp), %rax
movq %rax, 0x50(%r12)
andq $0x0, 0x50(%rsp)
pushq $0x20
popq %rdi
callq 0x5390
leaq 0x15158(%rip), %rcx     # 0x1d7d8
movq %rcx, (%rax)
movq %rbp, 0x8(%rax)
leaq 0x2a5c(%rip), %rcx      # 0xb0ea
movq %rcx, 0x10(%rax)
andq $0x0, 0x18(%rax)
movq %rax, 0x120(%rsp)
leaq 0x50(%rsp), %rdi
leaq 0x120(%rsp), %rsi
xorl %edx, %edx
callq 0x5310
movq 0x120(%rsp), %rdi
testq %rdi, %rdi
je 0x86c6
movq (%rdi), %rax
callq *0x8(%rax)
movq %r12, %rdi
addq $0x30, %rdi
leaq 0x50(%rsp), %r15
movq %r15, %rsi
callq 0xc810
movq %r15, %rdi
callq 0xc82a
andq $0x0, 0xc8(%rsp)
leaq 0xc0(%rsp), %rdi
callq 0xb074
xorps %xmm0, %xmm0
movaps %xmm0, 0x100(%rsp)
movaps 0xa0(%rsp), %xmm0
movq %rbp, 0xa0(%rsp)
movq %r12, 0xa8(%rsp)
movaps %xmm0, 0xc0(%rsp)
leaq 0xc8(%rsp), %rdi
callq 0xc0d4
leaq 0x108(%rsp), %rdi
callq 0xc0d4
cmpq $0x0, 0xa0(%rsp)
jne 0x8836
pushq $0x48
popq %rdi
callq 0x5390
movq %rax, %r12
leaq 0x120(%rsp), %rax
movq %rax, 0xc0(%rsp)
movq %r12, 0xc8(%rsp)
movabsq $0x100000001, %rax      # imm = 0x100000001
movq %rax, 0x8(%r12)
leaq 0x15093(%rip), %rax     # 0x1d818
movq %rax, (%r12)
movq %r12, %rbp
addq $0x10, %rbp
andq $0x0, 0x18(%r12)
andl $0x0, 0x20(%r12)
movb $0x0, 0x24(%r12)
andl $0x0, 0x28(%r12)
leaq 0x150b9(%rip), %rax     # 0x1d868
movq %rax, 0x10(%r12)
pushq $0x30
popq %rdi
callq 0x5390
movq %rax, %r15
movq %rax, %rdi
callq 0xd8be
movq %r15, 0x30(%r12)
movq %rbx, 0x38(%r12)
movq 0x10(%rsp), %rax
movq %rax, 0x40(%r12)
andq $0x0, 0xc8(%rsp)
leaq 0xc0(%rsp), %rdi
callq 0xb788
xorps %xmm0, %xmm0
movaps %xmm0, 0x100(%rsp)
movaps 0xa0(%rsp), %xmm0
movq %rbp, 0xa0(%rsp)
movq %r12, 0xa8(%rsp)
movaps %xmm0, 0xc0(%rsp)
leaq 0xc8(%rsp), %rdi
callq 0xc0d4
leaq 0x108(%rsp), %rdi
callq 0xc0d4
movq %r14, %r15
movq %r14, %rdi
leaq 0xa0(%rsp), %rsi
callq 0xde56
movq 0x28(%rsp), %r14
movq %r13, %rbp
leaq 0xa8(%rsp), %rdi
callq 0xc0d4
movq 0x168(%rsp), %rdi
addq %r14, %rdi
movq %r15, %rsi
callq 0xbb8c
leaq 0x38(%rsp), %rdi
callq 0xc0d4
incq %rbx
addq $0x10, %r14
jmp 0x8595
xorl %ebx, %ebx
leaq 0x168(%rsp), %r15
leaq 0xc0(%rsp), %r12
leaq 0x68(%rsp), %r13
cmpq %rbx, 0x18(%rsp)
je 0x88fa
movq %r15, %rdi
movq %rbx, %rsi
callq 0xbbba
movq %r12, %rdi
movq %rax, %rsi
callq 0xbbdc
movq %r13, %rdi
movq %rbx, %rsi
callq 0xbc30
movq %rax, %rdi
movq %r12, %rsi
callq 0xdf48
movq %r12, %rdi
callq 0xbc4e
movq %rbp, %rdi
movq %rbx, %rsi
callq 0x6f22
movq (%rax), %rdi
movq 0x10(%rsp), %rax
movq 0x60(%rax), %rsi
callq 0xf644
incq %rbx
jmp 0x889e
movq 0x156af(%rip), %rdi     # 0x1dfb0
callq 0x5180
movq 0x156a3(%rip), %rdi     # 0x1dfb0
leaq 0xb444(%rip), %rsi      # 0x13d58
callq 0x5380
movq %rax, %rdi
callq 0x5180
xorps %xmm0, %xmm0
leaq 0xc0(%rsp), %rdi
movaps %xmm0, (%rdi)
andq $0x0, 0x10(%rdi)
movq 0x70(%rsp), %rax
subq 0x68(%rsp), %rax
pushq $0x18
popq %rcx
cqto
idivq %rcx
movq %rax, %rsi
callq 0xbc70
leaq 0xa0(%rsp), %rcx
xorps %xmm0, %xmm0
movaps %xmm0, (%rcx)
andq $0x0, 0x10(%rcx)
leaq 0x100(%rsp), %rdi
leaq 0x68(%rsp), %rdx
movq 0x10(%rsp), %rsi
callq 0x9722
andq $0x0, 0x40(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x30(%rsp)
leaq 0x120(%rsp), %rbx
movaps %xmm0, (%rbx)
andq $0x0, 0x10(%rbx)
movq 0x68(%rsp), %rsi
movq 0x70(%rsp), %rcx
movq %rcx, %rax
subq %rsi, %rax
cqto
pushq $0x18
popq %rdi
idivq %rdi
movzbl 0xc(%rsp), %r15d
notq %r15
addq %rax, %r15
xorl %r12d, %r12d
leaq 0x50(%rsp), %r14
subq %rsi, %rcx
movq %rcx, %rax
cqto
pushq $0x18
popq %rcx
idivq %rcx
cmpq %rax, %r12
jae 0x89fa
andq $0x0, 0x50(%rsp)
movq %r15, 0x58(%rsp)
movq %rbx, %rdi
movq %r14, %rsi
callq 0xe25e
incq %r12
movq 0x68(%rsp), %rsi
movq 0x70(%rsp), %rcx
jmp 0x89c2
xorl %ebx, %ebx
leaq 0xa0(%rsp), %r14
leaq 0x50(%rsp), %r15
leaq 0x80(%rsp), %r12
leaq 0x30(%rsp), %r13
movq 0x68(%rsp), %rsi
movq 0x70(%rsp), %rcx
movq %rcx, %rax
subq %rsi, %rax
cqto
pushq $0x18
popq %rdi
idivq %rdi
xorps %xmm0, %xmm0
cmpq %rax, %rbx
jae 0x8b25
movaps %xmm0, 0x50(%rsp)
andq $0x0, 0x60(%rsp)
xorl %ebp, %ebp
subq %rsi, %rcx
movq %rcx, %rax
cqto
pushq $0x18
popq %rcx
idivq %rcx
cmpq %rax, %rbp
jae 0x8adf
cmpb $0x0, 0xc(%rsp)
je 0x8a95
movq %r14, %rdi
movq %rbx, %rsi
callq 0xbca6
cmpq (%rax), %rbp
jne 0x8ab2
movb $0x1, 0x80(%rsp)
movl $0xfffffffe, 0x84(%rsp) # imm = 0xFFFFFFFE
movq %r15, %rdi
movq %r12, %rsi
callq 0xe3ba
jmp 0x8acd
movb $0x0, 0x80(%rsp)
orl $-0x1, 0x84(%rsp)
movq %r15, %rdi
movq %r12, %rsi
callq 0xe3ba
jmp 0x8acd
movb $0x0, 0x80(%rsp)
orl $-0x1, 0x84(%rsp)
movq %r15, %rdi
movq %r12, %rsi
callq 0xe3ba
incq %rbp
movq 0x68(%rsp), %rsi
movq 0x70(%rsp), %rcx
jmp 0x8a47
movq %r13, %rdi
movq %r15, %rsi
callq 0xbcc8
movq %r15, %rdi
callq 0x7140
incq %rbx
cmpb $0x0, 0xc(%rsp)
jne 0x8a16
xorps %xmm0, %xmm0
andq $0x0, 0x60(%rsp)
movaps %xmm0, 0x50(%rsp)
movq 0x70(%rsp), %rax
subq 0x68(%rsp), %rax
cqto
pushq $0x18
popq %rcx
idivq %rcx
jmp 0x9180
movaps %xmm0, 0x50(%rsp)
andq $0x0, 0x60(%rsp)
cmpb $0x0, 0xc(%rsp)
je 0x9180
movq %rax, %rcx
decq %rcx
leaq 0x140(%rsp), %rdx
movq %rcx, (%rdx)
leaq 0x80(%rsp), %rdi
leaq 0x7(%rsp), %rcx
movq %rax, %rsi
callq 0xbcf4
leaq 0x50(%rsp), %rdi
leaq 0x80(%rsp), %rbx
movq %rbx, %rsi
callq 0xe7ce
movq %rbx, %rdi
callq 0xc19e
movss 0xae42(%rip), %xmm0     # 0x139c8
movq $0x0, 0x20(%rsp)
leaq 0x80(%rsp), %r13
movl $0x0, 0x8(%rsp)
movss %xmm0, 0x28(%rsp)
movss 0x28(%rsp), %xmm0
ucomiss 0xae1a(%rip), %xmm0     # 0x139cc
jbe 0x9147
movq 0x100(%rsp), %rax
movq 0x108(%rsp), %rcx
movq %rcx, 0x160(%rsp)
xorl %r14d, %r14d
movq %rax, 0xf0(%rsp)
cmpq 0x160(%rsp), %rax
je 0x9012
movq %r14, 0x18(%rsp)
movq 0x70(%rsp), %rax
subq 0x68(%rsp), %rax
cqto
pushq $0x18
popq %rcx
idivq %rcx
xorps %xmm0, %xmm0
movaps %xmm0, 0x140(%rsp)
movq %r13, %rdi
movq %rax, %rsi
leaq 0x140(%rsp), %rdx
leaq 0x7(%rsp), %rcx
callq 0xbdbc
movq 0xf0(%rsp), %rax
movq (%rax), %r15
movq 0x8(%rax), %r12
movq $0x0, 0xf8(%rsp)
xorl %ebx, %ebx
cmpq %r12, %r15
je 0x8c98
movq 0x8(%r15), %r14
movq 0x10(%r15), %rbp
cmpq %r14, %rbp
je 0x8c8d
cmpb $0x1, (%r15)
jne 0x8c62
incq 0xf8(%rsp)
jmp 0x8c8d
incq %rbx
jmp 0x8c8d
movq (%r14), %rsi
cmpb $0x1, (%r15)
jne 0x8c7a
movq %r13, %rdi
callq 0xbe12
jmp 0x8c86
movq %r13, %rdi
callq 0xbe12
addq $0x8, %rax
incq (%rax)
addq $0x8, %r14
cmpq %rbp, %r14
jne 0x8c67
addq $0x20, %r15
jmp 0x8c40
movq 0xf8(%rsp), %rcx
testq %rcx, %rcx
js 0x8cac
cvtsi2ss %rcx, %xmm0
jmp 0x8cc1
movq %rcx, %rax
shrq %rax
andl $0x1, %ecx
orq %rax, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
movss %xmm0, 0xe0(%rsp)
movq 0x18(%rsp), %r14
movq %rbx, %r12
testq %rbx, %rbx
js 0x8cde
cvtsi2ss %r12, %xmm0
jmp 0x8cf6
movq %r12, %rax
shrq %rax
movl %r12d, %ecx
andl $0x1, %ecx
orq %rax, %rcx
cvtsi2ss %rcx, %xmm0
addss %xmm0, %xmm0
movss %xmm0, 0xe4(%rsp)
movq 0xf8(%rsp), %rbx
xorl %r15d, %r15d
movq 0x70(%rsp), %rax
subq 0x68(%rsp), %rax
cqto
pushq $0x18
popq %rcx
idivq %rcx
cmpq %rax, %r15
jae 0x8f2a
movq %r13, %rdi
movq %r15, %rsi
callq 0xbe12
cmpq $0x0, (%rax)
jne 0x8d4c
movq %r13, %rdi
movq %r15, %rsi
callq 0xbe12
cmpq $0x0, 0x8(%rax)
je 0x8dd0
cmpq %rbx, %r12
jbe 0x8d6c
movq %r13, %rdi
movq %r15, %rsi
callq 0xbe12
movq 0x8(%rax), %rax
testq %rax, %rax
js 0x8d8b
cvtsi2ss %rax, %xmm0
jmp 0x8da0
testq %rbx, %rbx
je 0x8dd0
movq %r13, %rdi
movq %r15, %rsi
callq 0xbe12
movq (%rax), %rax
testq %rax, %rax
js 0x8dab
cvtsi2ss %rax, %xmm0
jmp 0x8dc0
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
cvtsi2ss %rax, %xmm0
addss %xmm0, %xmm0
divss 0xe4(%rsp), %xmm0
jmp 0x8dc9
movq %rax, %rcx
shrq %rcx
andl $0x1, %eax
orq %rcx, %rax
cvtsi2ss %rax, %xmm0
addss %xmm0, %xmm0
divss 0xe0(%rsp), %xmm0
ucomiss 0x28(%rsp), %xmm0
jae 0x8dd8
incq %r15
jmp 0x8d0a
movq %r13, %rdi
movq %r15, %rsi
callq 0xbe12
andq $0x0, (%rax)
movq %r13, %rdi
movq %r15, %rsi
callq 0xbe12
andq $0x0, 0x8(%rax)
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0x7028
movq %rax, %rdi
movq %r15, %rsi
callq 0x7046
movb $0x0, (%rax)
cmpq %rbx, %r12
jbe 0x8e4d
leaq 0x120(%rsp), %rdi
movq %r14, %rsi
callq 0xbe12
movq 0x8(%rax), %rbx
leaq -0x1(%rbx), %rcx
movq %rcx, 0x8(%rax)
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0x7028
movq %rax, %rdi
movq %r15, %rsi
callq 0x7046
jmp 0x8e7f
leaq 0x120(%rsp), %rdi
movq %r14, %rsi
callq 0xbe12
movq (%rax), %rbx
leaq 0x1(%rbx), %rcx
movq %rcx, (%rax)
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0x7028
movq %rax, %rdi
movq %r15, %rsi
callq 0x7046
movl %ebx, 0x4(%rax)
leaq 0x50(%rsp), %rdi
movq %r14, %rsi
callq 0xbca6
decq (%rax)
movq 0xf0(%rsp), %rax
movq (%rax), %r12
movq 0x8(%rax), %r14
cmpq %r14, %r12
je 0x8f17
leaq 0x50(%rsp), %rdi
movq 0x18(%rsp), %rsi
callq 0xbca6
cmpq $0x0, (%rax)
jne 0x8ecc
movq 0x8(%r12), %rax
cmpq %rax, 0x10(%r12)
je 0x8ecc
movq %rax, 0x10(%r12)
leaq 0x8(%r12), %rbp
xorl %ebx, %ebx
movq 0x10(%r12), %rax
subq 0x8(%r12), %rax
sarq $0x3, %rax
cmpq %rax, %rbx
jae 0x8f11
movq %rbp, %rdi
movq %rbx, %rsi
callq 0xbca6
cmpq %r15, (%rax)
jne 0x8f0c
leaq (,%rbx,8), %rsi
addq (%rbp), %rsi
movq %rbp, %rdi
callq 0xbe34
jmp 0x8ed3
incq %rbx
jmp 0x8ed3
addq $0x20, %r12
jmp 0x8ea1
movss 0xaaa9(%rip), %xmm0     # 0x139c8
movss %xmm0, 0x28(%rsp)
movq 0x18(%rsp), %r14
leaq 0x50(%rsp), %rdi
movq %r14, %rsi
callq 0xbca6
cmpq $0x1, (%rax)
jne 0x8ff6
xorl %r15d, %r15d
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0x7028
movq 0x8(%rax), %rcx
subq (%rax), %rcx
sarq $0x3, %rcx
cmpq %rcx, %r15
jae 0x8ff6
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0x7028
movq %rax, %rdi
movq %r15, %rsi
callq 0x7046
cmpl $-0x1, 0x4(%rax)
je 0x8f88
incq %r15
jmp 0x8f44
leaq 0x120(%rsp), %rdi
movq %r14, %rsi
callq 0xbe12
movq (%rax), %rbx
leaq 0x1(%rbx), %rcx
movq %rcx, (%rax)
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0x7028
movq %rax, %rdi
movq %r15, %rsi
callq 0x7046
movl %ebx, 0x4(%rax)
leaq 0x50(%rsp), %rdi
movq %r14, %rsi
callq 0xbca6
andq $0x0, (%rax)
movq 0xf0(%rsp), %rcx
movq (%rcx), %rax
movq 0x8(%rcx), %rcx
cmpq %rcx, %rax
je 0x8ff6
movq 0x8(%rax), %rdx
cmpq %rdx, 0x10(%rax)
je 0x8ff0
movq %rdx, 0x10(%rax)
addq $0x20, %rax
jmp 0x8fdd
incq %r14
movq %r13, %rdi
callq 0xe250
movq 0xf0(%rsp), %rax
addq $0x18, %rax
jmp 0x8bd3
movss 0x28(%rsp), %xmm0
addss 0xa9b0(%rip), %xmm0     # 0x139d0
movss %xmm0, 0x28(%rsp)
cmpb $0x0, 0xc(%rsp)
je 0x912c
pushq $-0x1
popq %rbx
pushq $0x1
popq %r14
movq 0x38(%rsp), %rax
subq 0x30(%rsp), %rax
cqto
pushq $0x18
popq %rcx
idivq %rcx
cmpq %rax, %r14
jae 0x912c
leaq -0x1(%r14), %r15
xorl %ebp, %ebp
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0x7028
movq 0x8(%rax), %rcx
subq (%rax), %rcx
sarq $0x3, %rcx
cmpq %rcx, %rbp
jae 0x9124
leaq 0x30(%rsp), %rdi
movq %r14, %rsi
callq 0x7028
movq %rax, %rdi
movq %rbp, %rsi
callq 0x7046
cmpb $0x1, (%rax)
jne 0x911c
leaq 0x30(%rsp), %rdi
movq %r15, %rsi
callq 0x7028
movq %rax, %rdi
movq %rbp, %rsi
callq 0x7046
movl 0x4(%rax), %eax
cmpl $-0x1, %eax
je 0x911c
cmpl $-0x1, %ebx
je 0x90d5
cmpl %ebx, %eax
jle 0x90d9
pushq $0x1
popq %rax
movq %rax, 0x20(%rsp)
pushq $0x2
popq %rax
movl %eax, 0x8(%rsp)
jmp 0x911c
movl %eax, %ebx
jmp 0x911c
jge 0x90df
pushq $0x1
jmp 0x9110
testl %eax, %eax
je 0x910e
movq 0x10(%rsp), %rdx
movq 0x48(%rdx), %rcx
subq 0x40(%rdx), %rcx
shrq $0x3, %rcx
decl %ecx
pushq $0x2
popq %rdx
movq %rdx, 0x20(%rsp)
pushq $0x1
popq %rdx
movl %edx, 0x8(%rsp)
cmpl %ecx, %eax
je 0x911c
jmp 0x9255
pushq $0x2
popq %rcx
movl %ecx, %eax
movq %rax, 0x20(%rsp)
movl %ecx, 0x8(%rsp)
incq %rbp
jmp 0x9059
incq %r14
jmp 0x9038
cmpl $0x0, 0x8(%rsp)
setne %al
cmpl $0x0, 0x20(%rsp)
setne %cl
andb %al, %cl
cmpb $0x1, %cl
jne 0x8ba5
movl 0x8(%rsp), %eax
orl 0x20(%rsp), %eax
sete %al
movl 0xc(%rsp), %ecx
andb %cl, %al
cmpb $0x1, %al
jne 0x9309
movq 0x14e89(%rip), %rdi     # 0x1dff0
leaq 0xac31(%rip), %rsi      # 0x13d9f
callq 0x5380
movq %rax, %rdi
callq 0x5180
jmp 0x9270
leaq 0x140(%rsp), %rdx
movq %rax, (%rdx)
leaq 0x80(%rsp), %rdi
pushq $0x1
popq %rsi
leaq 0x7(%rsp), %rcx
callq 0xbcf4
leaq 0x50(%rsp), %rdi
leaq 0x80(%rsp), %rbx
movq %rbx, %rsi
callq 0xe7ce
movq %rbx, %rdi
callq 0xc19e
leaq 0x100(%rsp), %rbx
pushq $0x1
popq %r14
movq 0x108(%rsp), %rax
subq 0x100(%rsp), %rax
cqto
pushq $0x18
popq %rcx
idivq %rcx
cmpq $0x2, %rax
jb 0x8b7e
xorl %r15d, %r15d
movq %rbx, %rdi
movq %r14, %rsi
callq 0xbd4a
movq 0x8(%rax), %rcx
subq (%rax), %rcx
sarq $0x5, %rcx
cmpq %rcx, %r15
jae 0x923c
movq %rbx, %rdi
xorl %esi, %esi
callq 0xbd4a
movq %rax, %r12
movq %rbx, %rdi
movq %r14, %rsi
callq 0xbd4a
movq %rax, %rdi
movq %r15, %rsi
callq 0xbd94
movq %r12, %rdi
movq %rax, %rsi
callq 0xbd68
incq %r15
jmp 0x91ee
movq 0x100(%rsp), %rsi
addq $0x18, %rsi
movq %rbx, %rdi
callq 0xbdb6
jmp 0x91c9
movq 0x14d94(%rip), %rdi     # 0x1dff0
leaq 0xab14(%rip), %rsi      # 0x13d77
callq 0x5380
movq %rax, %rdi
callq 0x5180
xorps %xmm0, %xmm0
movq 0xe8(%rsp), %rax
movups %xmm0, (%rax)
andq $0x0, 0x10(%rax)
leaq 0x50(%rsp), %rdi
callq 0xc19e
leaq 0x120(%rsp), %rdi
callq 0xe250
leaq 0x30(%rsp), %rdi
callq 0x6eb2
leaq 0x100(%rsp), %rdi
callq 0xbe8e
leaq 0xa0(%rsp), %rdi
callq 0xc19e
leaq 0xc0(%rsp), %rdi
callq 0xbe8e
leaq 0x68(%rsp), %rdi
callq 0xbeb0
leaq 0x168(%rsp), %rdi
callq 0xbed2
leaq 0x180(%rsp), %rdi
callq 0xc592
movq 0x158(%rsp), %rax
addq $0x198, %rsp            # imm = 0x198
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testb %cl, %cl
je 0x94de
xorps %xmm0, %xmm0
movaps %xmm0, 0x80(%rsp)
andq $0x0, 0x90(%rsp)
cmpl $0x2, 0x8(%rsp)
jne 0x9372
xorl %ebx, %ebx
leaq 0xa0(%rsp), %r14
leaq 0x80(%rsp), %r15
movq 0xa8(%rsp), %rax
subq 0xa0(%rsp), %rax
sarq $0x3, %rax
cmpq %rax, %rbx
jae 0x93c0
movq %r14, %rdi
movq %rbx, %rsi
callq 0xbca6
movq %r15, %rdi
movq %rax, %rsi
callq 0xbe6e
incq %rbx
jmp 0x933e
pushq $-0x1
popq %r15
xorl %r12d, %r12d
leaq 0xa0(%rsp), %rbx
leaq 0x80(%rsp), %r14
movq 0xa8(%rsp), %rsi
subq 0xa0(%rsp), %rsi
sarq $0x3, %rsi
cmpq %rsi, %r12
jae 0x93c0
addq %r15, %rsi
movq %rbx, %rdi
callq 0xbca6
decq %r15
incq %r12
movq %r14, %rdi
movq %rax, %rsi
callq 0xbe6e
jmp 0x9389
cmpl $0x1, 0x20(%rsp)
sete %al
cmpl $0x1, 0x8(%rsp)
sete %cl
orb %al, %cl
movb %cl, 0x18(%rsp)
leaq 0x30(%rsp), %rbx
leaq 0x80(%rsp), %r14
xorl %r15d, %r15d
movq 0x38(%rsp), %rax
subq 0x30(%rsp), %rax
cqto
pushq $0x18
popq %rcx
idivq %rcx
cmpq %rax, %r15
jae 0x94d1
cmpl $0x1, 0x20(%rsp)
movq %r15, %r12
movl $0x0, %eax
cmoveq %rax, %r12
cmpb $0x0, 0x18(%rsp)
jne 0x9430
movq 0x10(%rsp), %rax
movq 0x48(%rax), %r12
subq 0x40(%rax), %r12
sarq $0x3, %r12
subq %r15, %r12
incq %r12
xorl %r13d, %r13d
movq %rbx, %rdi
movq %r15, %rsi
callq 0x7028
movq 0x8(%rax), %rcx
subq (%rax), %rcx
sarq $0x3, %rcx
cmpq %rcx, %r13
jae 0x94c9
movq %rbx, %rdi
movq %r15, %rsi
callq 0x7028
movq %rax, %rbp
movq %r14, %rdi
movq %r13, %rsi
callq 0xbca6
movq (%rax), %rsi
movq %rbp, %rdi
callq 0x7046
cmpb $0x0, (%rax)
jne 0x94c1
movq %rbx, %rdi
movq %r15, %rsi
callq 0x7028
movq %rax, %rbp
movq %r14, %rdi
movq %r13, %rsi
callq 0xbca6
movq (%rax), %rsi
movq %rbp, %rdi
callq 0x7046
movl %r12d, 0x4(%rax)
incq %r12
movq 0x10(%rsp), %rax
movq 0x48(%rax), %rcx
subq 0x40(%rax), %rcx
sarq $0x3, %rcx
decq %rcx
movq %r12, %rax
xorl %edx, %edx
divq %rcx
movq %rdx, %r12
incq %r13
jmp 0x9433
incq %r15
jmp 0x93e6
leaq 0x80(%rsp), %rdi
callq 0xc19e
leaq 0x30(%rsp), %rbx
movq 0x10(%rsp), %rdi
movq %rbx, %rsi
callq 0xa258
movaps 0x30(%rsp), %xmm0
movq 0xe8(%rsp), %rcx
movups %xmm0, (%rcx)
movq 0x40(%rsp), %rax
movq %rax, 0x10(%rcx)
movq %rbx, 0xe8(%rsp)
jmp 0x9270
jmp 0x9695
jmp 0x9695
jmp 0x9695
movq %rax, %r14
jmp 0x96dc
movq %rax, %r14
jmp 0x96e9
movq %rax, %r14
jmp 0x9700
movq %rax, %r14
jmp 0x970d
jmp 0x9666
jmp 0x9666
jmp 0x9695
jmp 0x9654
movq %rax, %r14
movq %rbp, %rdi
callq 0xc894
leaq 0xc0(%rsp), %rdi
callq 0xb788
jmp 0x963a
jmp 0x95a7
jmp 0x967a
jmp 0x9695
movq %rax, %r14
jmp 0x96b8
movq %rax, %r14
leaq 0xc0(%rsp), %rdi
callq 0xbc4e
jmp 0x96f6
movq %rdx, %rbx
movq %rax, %r14
jmp 0x95f9
movq %rax, %r14
jmp 0x963a
movq %rdx, %rbx
movq %rax, %r14
jmp 0x95e4
movq %rdx, %rbx
movq %rax, %r14
jmp 0x95d8
movq %rdx, %rbx
movq %rax, %r14
movq 0x120(%rsp), %rdi
testq %rdi, %rdi
je 0x95d8
movq (%rdi), %rax
callq *0x8(%rax)
addq $0x40, %r12
movq %r12, %rdi
callq 0xd8e0
movq %rbp, %rdi
callq 0xc862
leaq 0xc0(%rsp), %rdi
callq 0xb074
cmpl $0x1, %ebx
jne 0x963a
movq %r14, %rdi
callq 0x5140
leaq 0x10(%rax), %rbx
callq 0x51a0
leaq 0x100(%rsp), %rsi
movl $0xb, (%rsi)
movq %rax, 0x8(%rsi)
movq %rbx, %rdi
callq 0xc7e4
callq 0x54f0
jmp 0x9654
jmp 0x9654
movq %rax, %r14
callq 0x55a0
leaq 0xa8(%rsp), %rdi
callq 0xc0d4
jmp 0x96f6
movq %rax, %rdi
callq 0x7100
movq %rax, %r14
jmp 0x96f6
jmp 0x969e
jmp 0x969e
jmp 0x9695
jmp 0x967a
jmp 0x967a
movq %rax, %r14
leaq 0x80(%rsp), %rdi
callq 0xc19e
jmp 0x96ae
jmp 0x967a
movq %rax, %r14
leaq 0x50(%rsp), %rdi
callq 0x7140
jmp 0x96b8
jmp 0x969e
jmp 0x9695
jmp 0x969e
jmp 0x969e
jmp 0x9695
jmp 0x969e
movq %rax, %r14
jmp 0x96ae
jmp 0x969e
jmp 0x969e
movq %rax, %r14
leaq 0x80(%rsp), %rdi
callq 0xe250
leaq 0x50(%rsp), %rdi
callq 0xc19e
leaq 0x120(%rsp), %rdi
callq 0xe250
leaq 0x30(%rsp), %rdi
callq 0x6eb2
leaq 0x100(%rsp), %rdi
callq 0xbe8e
leaq 0xa0(%rsp), %rdi
callq 0xc19e
leaq 0xc0(%rsp), %rdi
callq 0xbe8e
leaq 0x68(%rsp), %rdi
callq 0xbeb0
leaq 0x168(%rsp), %rdi
callq 0xbed2
leaq 0x180(%rsp), %rdi
callq 0xc592
movq %r14, %rdi
callq 0x5610