// File: /workspace/github_cpp_makefile_star2_O1/ksabry[P]bfbrute/src/ProgramIterator.h
// Function: ProgramIterator<400ul, 32ul, 12ul, 32ul>::Execute(char const*, unsigned long)
bool Execute(const char* initialData, const uint_fast32_t initialDataSize)
	{
		// TODO: short-circuit unbalanced linear loop if beyond bounds and ends on nonzero

		lastExecutionSuccessful = false;
		lastExecutionMaxProgramIdx = 0;

		uint_fast32_t programIdx = 0;
		dataIdx = data_size / 2 + cache_data_size;
		//dataBoundLow = dataIdx;
		//dataBoundHigh = dataIdx + 1;
		
		memset(data, 0, data_size + 2 * cache_data_size);
		memcpy(data + dataIdx, initialData, initialDataSize);

		uint_fast32_t remainingJumps = MAX_JUMPS;
		while (remainingJumps--)
		{
			assert(programIdx < iteratorCount);
			auto iteratorData = iterators[programIdx].Data();
			bool isLinear = jumps[programIdx].nonzero == programIdx;

			// Technically may be incorrect if iterator size is greater than 256
			//if (isLinear && dataIdx + iteratorData.idx < dataBoundLow && 
			//	iteratorData.data[iteratorData.idx] != 0) return false;
			//if (isLinear && dataIdx + iteratorData.idx >= dataBoundHigh &&
			//	iteratorData.data[iteratorData.idx] != 0) return false;
			//dataBoundLow = Min(dataBoundLow, dataIdx + iteratorData.start);
			//dataBoundHigh = Max(dataBoundHigh, dataIdx + iteratorData.end);

			if (isLinear && iterators[programIdx].IsBalanced())
			{
				uint8_t centerCell = iteratorData.data[iteratorData.idx + cache_data_size / 2];
				int cnt = divisionTable->Get(data[dataIdx], centerCell);
				if (cnt == -1)
				{
					return false;
				}

#ifdef SHORT_CIRCUIT_LINEAR_SINGULAR
				auto programSize = iteratorSizes[programIdx];
				if (programSize == centerCell || programSize == 256 - centerCell)
				{
					data[dataIdx] = 0; 
				}
				else ApplyDataMult(iteratorData, cnt);
#else
				ApplyDataMult(iteratorData.data, cnt);
#endif
				programIdx = jumps[programIdx].zero;
				continue;
			}

			uint_fast32_t newDataIdx = dataIdx + iteratorData.idx;
			if (newDataIdx < cache_data_size || newDataIdx >= data_size + cache_data_size)
			{
				return false;
			}
			
			ApplyData(iteratorData);
		
			dataIdx = newDataIdx;
			if (programIdx == iteratorCount - 1)
			{
				lastExecutionSuccessful = true;
				return true;
			}

			// TODO: test zero, nonzero in array
			programIdx = (data[dataIdx] == 0) ? jumps[programIdx].zero : jumps[programIdx].nonzero;
			if (programIdx > lastExecutionMaxProgramIdx)
			{
				lastExecutionMaxProgramIdx = programIdx;
			}
		}
		return false;
	}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rdx, %r15
movq %rsi, %r12
movq %rdi, %rbx
movb $0x0, 0x4468(%rdi)
movq $0x0, 0x4470(%rdi)
movq $0xe8, 0x4448(%rdi)
leaq 0x4278(%rdi), %r14
xorl %r13d, %r13d
movl $0x1d0, %edx            # imm = 0x1D0
movq %r14, %rdi
xorl %esi, %esi
callq 0x2100
leaq 0x4360(%rbx), %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x2190
leaq 0x128(%rbx), %rdx
leaq 0x4030(%rbx), %rsi
movl $0xc34f, %edi           # imm = 0xC34F
cmpq 0x20(%rbx), %r13
jae 0x7700
imulq $0x1e8, %r13, %rax      # imm = 0x1E8
movq 0x68(%rdx,%rax), %r9
movq %r9, 0x30(%rsp)
movups 0x38(%rdx,%rax), %xmm0
movups 0x48(%rdx,%rax), %xmm1
movups 0x58(%rdx,%rax), %xmm2
movaps %xmm2, 0x20(%rsp)
movaps %xmm1, 0x10(%rsp)
movaps %xmm0, (%rsp)
movq %r13, %r10
shlq $0x4, %r10
leaq (%rsi,%r10), %r9
cmpq %r13, 0x8(%rsi,%r10)
jne 0x75a4
addq %rdx, %rax
cmpq $0x0, 0x58(%rax)
je 0x764b
movq 0x4448(%rbx), %r11
movq 0x20(%rsp), %r10
leaq (%r10,%r11), %r15
addq $-0x1b0, %r15           # imm = 0xFE50
movl $0x1, %eax
cmpq $-0x190, %r15           # imm = 0xFE70
jae 0x75d0
xorl %ecx, %ecx
jmp 0x76dc
movq 0x28(%rsp), %r15
movq 0x30(%rsp), %r12
cmpq %r12, %r15
jge 0x75fa
movb 0x10(%rsp,%r15), %bpl
movq 0x4448(%rbx), %r8
addq %r14, %r8
addb %bpl, (%r15,%r8)
incq %r15
cmpq %r15, %r12
jne 0x75df
addq %r11, %r10
movq %r10, 0x4448(%rbx)
movq 0x20(%rbx), %r8
decq %r8
cmpq %r8, %r13
jne 0x761e
movb $0x1, 0x4468(%rbx)
movb $0x1, %cl
jmp 0x76dc
xorl %eax, %eax
cmpb $0x0, 0x4278(%rbx,%r10)
setne %al
movq (%r9,%rax,8), %r13
xorl %eax, %eax
cmpq 0x4470(%rbx), %r13
jbe 0x76dc
movq %r13, 0x4470(%rbx)
jmp 0x76dc
movq 0x20(%rsp), %rax
movq %rsp, %r8
movzbl 0x10(%rax,%r8), %r11d
movq 0x4448(%rbx), %rax
movzbl 0x4278(%rbx,%rax), %r10d
shll $0xa, %r10d
addq 0x4460(%rbx), %r10
movl (%r10,%r11,4), %r10d
cmpl $-0x1, %r10d
je 0x76c5
movq 0x28(%rbx,%r13,8), %r15
cmpq %r11, %r15
je 0x76cf
movl $0x100, %r12d           # imm = 0x100
subq %r11, %r12
cmpq %r12, %r15
je 0x76cf
movq 0x28(%rsp), %r11
movq 0x30(%rsp), %r15
cmpq %r15, %r11
jge 0x76d4
movb 0x10(%rsp,%r11), %al
mulb %r10b
movq 0x4448(%rbx), %r12
addq %r14, %r12
addb %al, (%r11,%r12)
incq %r11
cmpq %r11, %r15
jne 0x76a5
jmp 0x76d4
movl $0x1, %eax
jmp 0x75c9
movb $0x0, (%r14,%rax)
movq (%r9), %r13
movl $0x2, %eax
testb $0x1, %al
jne 0x76ec
subq $0x1, %rdi
jae 0x754c
xorl %ecx, %ecx
andb $0x1, %cl
movl %ecx, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x1fcb(%rip), %rdi      # 0x96d2
leaq 0x1b2b(%rip), %rsi      # 0x9239
leaq 0x1fd8(%rip), %rcx      # 0x96ed
movl $0x211, %edx            # imm = 0x211
callq 0x2120
nop