// File: /workspace/github_cpp_makefile_star2_O3/aisthesis[P]realnumber/src/array_arithmetic.cpp
// Function: array_arithmetic::divide(unsigned char const*, unsigned char const*, unsigned char*, unsigned long const&, unsigned long const&)
void divide(const unsigned char* dividend, const unsigned char* divisor, unsigned char* result,
			const std::size_t& len, const std::size_t& int_digits) {
		// throw exception if client tries to divide by 0
		if (helpers::is_zero(divisor, len)) {
			throw std::invalid_argument("Division by 0 is not allowed!");
    }
		// initialize result to 0
		helpers::set_to_zero(result, len);
		// we are done if dividend is 0, so return
		if (helpers::is_zero(dividend, len)) { return; }
		// we will need copies of double size for manipulation
		const std::size_t WORKING_LEN = len * 2;
		// this is the bit length of the original values (not the expanded copies)
		const std::size_t BIT_LENGTH = len * 8;
		// 2 dividend arrays are needed because we need to subtract, then use result as new dividend
		unsigned char* dividend_copy1 = new unsigned char[WORKING_LEN];
		unsigned char* dividend_copy2 = new unsigned char[WORKING_LEN];
		unsigned char* divisor_copy = new unsigned char[WORKING_LEN];
		// copy dividend into copy1 (we don't yet need to do anything with dividend_copy2)
		helpers::copy_into(dividend, dividend_copy1, len, WORKING_LEN);
		helpers::copy_into(divisor, divisor_copy, len, WORKING_LEN);
		int starting_bit = int_digits * 8 - 1;
		starting_bit += helpers::division::align(dividend_copy1, divisor_copy, WORKING_LEN);
		bool throw_overflow_exception = (starting_bit < 0);
		std::size_t nonnegative_starting_bit = starting_bit;
		if (!throw_overflow_exception) {
			while (nonnegative_starting_bit < BIT_LENGTH) {
				bits::set(result, nonnegative_starting_bit);
				subtract(dividend_copy1, divisor_copy, dividend_copy2, WORKING_LEN);
				nonnegative_starting_bit += helpers::division::readjust(dividend_copy2, divisor_copy, WORKING_LEN);
				// check the condition of the while loop since we are using double storage
				if (nonnegative_starting_bit >= BIT_LENGTH) { break; }
				bits::set(result, nonnegative_starting_bit);
				subtract(dividend_copy2, divisor_copy, dividend_copy1, WORKING_LEN);
				nonnegative_starting_bit += helpers::division::readjust(dividend_copy1, divisor_copy, WORKING_LEN);
			}
		}
		delete[] dividend_copy1;
		delete[] dividend_copy2;
		delete[] divisor_copy;
		if (throw_overflow_exception) {
			throw std::overflow_error("Result of division is too large to compute!");
		}
	}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq (%rcx), %rax
testq %rax, %rax
je 0x4a40
movq %rdi, %r14
cmpb $0x0, (%rsi)
jne 0x4826
movl $0x1, %edi
movq %rdi, %r10
cmpq %rdi, %rax
je 0x481d
leaq 0x1(%r10), %rdi
cmpb $0x0, (%rsi,%r10)
je 0x480a
cmpq %rax, %r10
jae 0x4a40
xorl %eax, %eax
movb $0x0, (%rdx,%rax)
incq %rax
movq (%rcx), %r13
cmpq %r13, %rax
jb 0x4828
testq %r13, %r13
je 0x4a31
cmpb $0x0, (%r14)
jne 0x4867
movl $0x1, %ecx
movq %rcx, %rax
cmpq %rcx, %r13
je 0x485e
leaq 0x1(%rax), %rcx
cmpb $0x0, (%r14,%rax)
je 0x484b
cmpq %r13, %rax
jae 0x4a31
movq %rdx, -0x40(%rbp)
movq %rsi, -0x58(%rbp)
movq %r8, -0x38(%rbp)
leaq (,%r13,2), %r12
movq %r12, -0x50(%rbp)
movq %r12, %rdi
callq 0x2030
movq %rax, %r15
movq %r12, %rdi
callq 0x2030
movq %rax, -0x60(%rbp)
movq %r12, %rdi
callq 0x2030
movq %rax, -0x30(%rbp)
movq %r15, %rdi
movq %r14, %rsi
movq %r13, %rdx
callq 0x2120
leaq (,%r13,8), %rax
movq %rax, -0x48(%rbp)
testq %r13, %r13
jle 0x48f6
movq %r15, %rdi
addq %r13, %rdi
xorl %esi, %esi
movq %r13, %rdx
callq 0x20b0
movq -0x30(%rbp), %r14
movq %r14, %rdi
movq -0x58(%rbp), %rsi
movq %r13, %rdx
callq 0x2120
addq %r13, %r14
movq %r14, %rdi
xorl %esi, %esi
movq %r13, %rdx
callq 0x20b0
jmp 0x4906
movq -0x30(%rbp), %rdi
movq -0x58(%rbp), %rsi
movq %r13, %rdx
callq 0x2120
movq -0x38(%rbp), %rax
movl (%rax), %r14d
leaq -0x50(%rbp), %rbx
movq %r15, %rdi
movq -0x30(%rbp), %r12
movq %r12, %rsi
movq %rbx, %rdx
callq 0x4266
movl %eax, %r13d
movq %r15, %rdi
movq %r12, %rsi
movq %rbx, %rdx
callq 0x43b3
leal (%r13,%r14,8), %ecx
addl %eax, %ecx
decl %ecx
testl %ecx, %ecx
sets %al
movq %r15, %r8
movl %ecx, -0x38(%rbp)
movslq %ecx, %r15
cmpq %r15, -0x48(%rbp)
setbe %cl
orb %al, %cl
movq -0x60(%rbp), %r13
movq -0x40(%rbp), %rbx
jne 0x4a12
movq %r15, %rax
movl %r15d, %ecx
notb %cl
andb $0x7, %cl
movb $0x1, %dl
shlb %cl, %dl
shrq $0x3, %rax
orb %dl, (%rbx,%rax)
movq %r8, %rdi
movq -0x30(%rbp), %r14
movq %r14, %rsi
movq %r13, %rdx
movq %r13, %rbx
leaq -0x50(%rbp), %r13
movq %r13, %rcx
movq %r8, %r12
callq 0x469d
movq %rbx, %rdi
movq %r14, %rsi
movq %r13, %rdx
movq %rbx, %r13
callq 0x447d
movq -0x40(%rbp), %rsi
movq %r12, %r8
movslq %eax, %r14
addq %r15, %r14
cmpq -0x48(%rbp), %r14
jae 0x4a12
movq %r14, %rax
movl %r14d, %ecx
notb %cl
andb $0x7, %cl
movb $0x1, %dl
shlb %cl, %dl
shrq $0x3, %rax
orb %dl, (%rsi,%rax)
movq %r13, %rdi
movq -0x30(%rbp), %r15
movq %r15, %rsi
movq %r8, %rdx
leaq -0x50(%rbp), %r13
movq %r13, %rcx
callq 0x469d
movq %r12, %rdi
movq %r15, %rsi
movq %r13, %rdx
movq %rbx, %r13
callq 0x447d
movq -0x40(%rbp), %rbx
movq %r12, %r8
movslq %eax, %r15
addq %r14, %r15
cmpq -0x48(%rbp), %r15
jb 0x4962
movq %r8, %rdi
callq 0x2190
movq %r13, %rdi
callq 0x2190
movq -0x30(%rbp), %rdi
callq 0x2190
cmpl $0x0, -0x38(%rbp)
js 0x4a6c
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x10, %edi
callq 0x20a0
movq %rax, %rbx
leaq 0x6b6(%rip), %rsi       # 0x510a
movq %rax, %rdi
callq 0x2230
movq 0x357d(%rip), %rsi      # 0x7fe0
movq 0x3566(%rip), %rdx      # 0x7fd0
jmp 0x4a96
movl $0x10, %edi
callq 0x20a0
movq %rax, %rbx
leaq 0x6a8(%rip), %rsi       # 0x5128
movq %rax, %rdi
callq 0x2050
movq 0x3529(%rip), %rsi      # 0x7fb8
movq 0x351a(%rip), %rdx      # 0x7fb0
movq %rbx, %rdi
callq 0x21f0
jmp 0x4aa0
movq %rax, %r14
movq %rbx, %rdi
callq 0x2100
movq %r14, %rdi
callq 0x2210