// File: /workspace/github_cpp_makefile_star2_O2/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 $0x48, %rsp
movq %rdi, %rbx
movb $0x0, 0x4468(%rdi)
andq $0x0, 0x4470(%rdi)
movq %rdx, %r15
movq %rsi, %r12
movq $0xe8, 0x4448(%rdi)
addq $0x4278, %rdi           # imm = 0x4278
xorl %r14d, %r14d
movl $0x1d0, %edx            # imm = 0x1D0
movq %rdi, (%rsp)
xorl %esi, %esi
callq 0x2100
leaq 0x4360(%rbx), %rdi
movq %r12, %rsi
movq %r15, %rdx
callq 0x2190
leaq 0x128(%rbx), %r12
leaq 0x4030(%rbx), %rax
movq %rax, 0x8(%rsp)
movq $-0xc350, %rbp          # imm = 0xFFFF3CB0
testq %rbp, %rbp
je 0x669c
cmpq 0x20(%rbx), %r14
jae 0x66b8
imulq $0x1e8, %r14, %rax      # imm = 0x1E8
movq 0x68(%r12,%rax), %rcx
movq %rcx, 0x40(%rsp)
movups 0x38(%r12,%rax), %xmm0
movups 0x48(%r12,%rax), %xmm1
movups 0x58(%r12,%rax), %xmm2
movaps %xmm2, 0x30(%rsp)
movaps %xmm1, 0x20(%rsp)
movaps %xmm0, 0x10(%rsp)
movq %r14, %rcx
shlq $0x4, %rcx
movq 0x8(%rsp), %rdx
leaq (%rdx,%rcx), %r15
cmpq %r14, 0x8(%rdx,%rcx)
jne 0x6622
addq %r12, %rax
cmpq $0x0, 0x58(%rax)
movq 0x4448(%rbx), %rax
jne 0x6629
movq 0x30(%rsp), %rcx
leaq 0x10(%rsp), %rdx
movzbl 0x10(%rcx,%rdx), %ecx
movzbl 0x4278(%rbx,%rax), %edx
shll $0xa, %edx
addq 0x4460(%rbx), %rdx
movl (%rdx,%rcx,4), %edx
cmpl $-0x1, %edx
je 0x669c
movq 0x28(%rbx,%r14,8), %rsi
cmpq %rcx, %rsi
je 0x6689
movl $0x100, %edi            # imm = 0x100
subq %rcx, %rdi
cmpq %rdi, %rsi
je 0x6689
movzbl %dl, %edx
movq %rbx, %rdi
leaq 0x10(%rsp), %rsi
callq 0x6e92
jmp 0x6691
movq 0x4448(%rbx), %rax
movq 0x30(%rsp), %r13
leaq (%rax,%r13), %rcx
addq $-0x1b0, %rcx           # imm = 0xFE50
cmpq $-0x190, %rcx           # imm = 0xFE70
jb 0x669c
addq %rax, %r13
movq %rbx, %rdi
leaq 0x10(%rsp), %rsi
callq 0x6ebe
movq %r13, 0x4448(%rbx)
movq 0x20(%rbx), %rax
decq %rax
cmpq %rax, %r14
je 0x66a0
xorl %eax, %eax
cmpb $0x0, 0x4278(%rbx,%r13)
setne %al
movq (%r15,%rax,8), %r14
cmpq 0x4470(%rbx), %r14
jbe 0x6694
movq %r14, 0x4470(%rbx)
jmp 0x6694
movq (%rsp), %rcx
movb $0x0, (%rcx,%rax)
movq (%r15), %r14
incq %rbp
jmp 0x655b
xorl %eax, %eax
jmp 0x66a9
movb $0x1, 0x4468(%rbx)
movb $0x1, %al
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x2097(%rip), %rdi      # 0x8756
leaq 0x1b73(%rip), %rsi      # 0x8239
leaq 0x20a4(%rip), %rcx      # 0x8771
movl $0x211, %edx            # imm = 0x211
callq 0x2120
nop