// File: /workspace/github_cpp_makefile_star2_O2/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 %r8, %r14
movq %rcx, %r13
movq %rdx, %rbx
movq %rsi, %r15
movq %rdi, %r12
movq %rsi, %rdi
movq %rcx, %rsi
callq 0x3ba8
testb %al, %al
jne 0x4224
movq %rbx, %rdi
movq %r13, %rsi
callq 0x3bcb
movq %r12, %rdi
movq %r13, %rsi
callq 0x3ba8
testb %al, %al
jne 0x4215
movq %r15, -0x30(%rbp)
movq (%r13), %r15
movq %r12, -0x50(%rbp)
leaq (%r15,%r15), %r12
leaq -0x38(%rbp), %rax
movq %r12, (%rax)
shlq $0x3, %r15
movq %r12, %rdi
callq 0x2030
movq %r14, -0x40(%rbp)
movq %rax, %r14
movq %r12, %rdi
callq 0x2030
movq %rax, -0x48(%rbp)
movq %r12, %rdi
callq 0x2030
movq %rax, %r12
movq -0x50(%rbp), %rdi
movq %r14, %rsi
movq %r13, %rdx
leaq -0x38(%rbp), %rcx
callq 0x3b07
movq -0x30(%rbp), %rdi
movq %r12, %rsi
movq %r13, %rdx
leaq -0x38(%rbp), %r13
movq %r13, %rcx
callq 0x3b07
movq %rbx, -0x30(%rbp)
movq -0x40(%rbp), %rax
movl (%rax), %ebx
movq %r14, %rdi
movq %r12, %rsi
movq %r13, %rdx
callq 0x3d2b
leal (%rax,%rbx,8), %ecx
decl %ecx
testl %ecx, %ecx
sets %al
movl %ecx, -0x40(%rbp)
movslq %ecx, %rbx
cmpq %rbx, %r15
setbe %cl
orb %al, %cl
jne 0x41f6
movq %r14, -0x58(%rbp)
movq %rbx, %rax
movl %ebx, %ecx
notb %cl
andb $0x7, %cl
movb $0x1, %dl
shlb %cl, %dl
shrq $0x3, %rax
movq -0x30(%rbp), %rcx
orb %dl, (%rcx,%rax)
movq %r14, %rdi
movq %r12, %rsi
movq -0x48(%rbp), %r13
movq %r13, %rdx
leaq -0x38(%rbp), %r14
movq %r14, %rcx
callq 0x3f15
movq %r13, %rdi
movq %r12, %rsi
movq %r14, %rdx
movq -0x58(%rbp), %r14
callq 0x3d61
movslq %eax, %r13
addq %rbx, %r13
cmpq %r15, %r13
jae 0x41f6
movq %r13, %rax
movl %r13d, %ecx
notb %cl
andb $0x7, %cl
movb $0x1, %dl
shlb %cl, %dl
shrq $0x3, %rax
movq -0x30(%rbp), %rcx
orb %dl, (%rcx,%rax)
movq -0x48(%rbp), %rdi
movq %r12, %rsi
movq %r14, %rdx
leaq -0x38(%rbp), %rbx
movq %rbx, %rcx
callq 0x3f15
movq %r14, %rdi
movq %r12, %rsi
movq %rbx, %rdx
callq 0x3d61
movslq %eax, %rbx
addq %r13, %rbx
cmpq %r15, %rbx
jb 0x415a
movq %r14, %rdi
callq 0x2160
movq -0x48(%rbp), %rdi
callq 0x2160
movq %r12, %rdi
callq 0x2160
cmpl $0x0, -0x40(%rbp)
js 0x424e
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $0x10
popq %rdi
callq 0x20a0
movq %rax, %rbx
leaq 0xed4(%rip), %rsi       # 0x510a
movq %rax, %rdi
callq 0x21f0
movq 0x3d9b(%rip), %rsi      # 0x7fe0
movq 0x3d84(%rip), %rdx      # 0x7fd0
jmp 0x4276
pushq $0x10
popq %rdi
callq 0x20a0
movq %rax, %rbx
leaq 0xec8(%rip), %rsi       # 0x5128
movq %rax, %rdi
callq 0x2040
movq 0x3d49(%rip), %rsi      # 0x7fb8
movq 0x3d3a(%rip), %rdx      # 0x7fb0
movq %rbx, %rdi
callq 0x21b0
jmp 0x4280
movq %rax, %r14
movq %rbx, %rdi
callq 0x20e0
movq %r14, %rdi
callq 0x21d0