// File: /workspace/github_cpp_makefile_star2_O1/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 %rsi, %r14
movq (%rcx), %rax
testq %rax, %rax
sete %sil
je 0x486f
cmpb $0x0, (%r14)
jne 0x486f
movl $0x1, %esi
movq %rsi, %r9
cmpq %rsi, %rax
je 0x4868
leaq 0x1(%r9), %rsi
cmpb $0x0, (%r14,%r9)
je 0x4855
cmpq %rax, %r9
setae %sil
testb %sil, %sil
jne 0x4aa3
testq %rax, %rax
je 0x488b
xorl %eax, %eax
movb $0x0, (%rdx,%rax)
incq %rax
cmpq (%rcx), %rax
jb 0x487f
movq (%rcx), %r13
testq %r13, %r13
sete %al
je 0x48b8
cmpb $0x0, (%rdi)
jne 0x48b8
movl $0x1, %ecx
movq %rcx, %rax
cmpq %rcx, %r13
je 0x48b2
leaq 0x1(%rax), %rcx
cmpb $0x0, (%rdi,%rax)
je 0x48a0
cmpq %r13, %rax
setae %al
testb %al, %al
jne 0x4a94
movq %r8, %rbx
movq %rdi, -0x30(%rbp)
movq %rdx, -0x48(%rbp)
leaq (,%r13,2), %r12
movq %r12, -0x50(%rbp)
movq %r12, %rdi
callq 0x2030
movq %rax, %r15
movq %r12, %rdi
callq 0x2030
movq %rax, -0x40(%rbp)
movq %r12, -0x38(%rbp)
movq %r12, %rdi
callq 0x2030
movq %rax, %r12
testq %r13, %r13
je 0x4916
movq %r15, %rdi
movq -0x30(%rbp), %rsi
movq %r13, %rdx
callq 0x2120
movq %r13, %rax
jmp 0x4918
xorl %eax, %eax
cmpq -0x38(%rbp), %rax
jae 0x492e
movq %r15, %rdi
addq %r13, %rdi
xorl %esi, %esi
movq %r13, %rdx
callq 0x20b0
movq %rbx, -0x58(%rbp)
testq %r13, %r13
je 0x494d
movq %r12, %rbx
movq %r12, %rdi
movq %r14, %rsi
movq %r13, %rdx
callq 0x2120
movq %r13, %rax
jmp 0x4952
movq %r12, %rbx
xorl %eax, %eax
leaq (,%r13,8), %rcx
movq %rcx, -0x30(%rbp)
cmpq -0x38(%rbp), %rax
jae 0x4974
movq %rbx, %rdi
addq %r13, %rdi
xorl %esi, %esi
movq %r13, %rdx
callq 0x20b0
movq -0x58(%rbp), %rax
movl (%rax), %r14d
leaq -0x50(%rbp), %r12
movq %r15, %rdi
movq %rbx, %rsi
movq %r12, %rdx
callq 0x4279
movl %eax, %r13d
movq %r15, %rdi
movq %rbx, %rsi
movq %r12, %rdx
callq 0x43db
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, -0x30(%rbp)
setbe %cl
orb %al, %cl
movq -0x48(%rbp), %rsi
jne 0x4a75
movq %r15, %rax
movl %r15d, %ecx
notb %cl
andb $0x7, %cl
movb $0x1, %dl
shlb %cl, %dl
shrq $0x3, %rax
orb %dl, (%rsi,%rax)
movq %r8, %rdi
movq %rbx, %rsi
movq -0x40(%rbp), %r14
movq %r14, %rdx
movq %rbx, %r12
leaq -0x50(%rbp), %rbx
movq %rbx, %rcx
movq %r8, %r13
callq 0x46e7
movq %r14, %rdi
movq %r12, %rsi
movq %rbx, %rdx
movq %r12, %rbx
callq 0x44b5
movq %r13, %r8
movq -0x48(%rbp), %rsi
movslq %eax, %r14
addq %r15, %r14
cmpq -0x30(%rbp), %r14
jae 0x4a75
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 -0x40(%rbp), %rdi
movq %rbx, %rsi
movq %r8, %rdx
leaq -0x50(%rbp), %rbx
movq %rbx, %rcx
callq 0x46e7
movq %r13, %rdi
movq %r12, %rsi
movq %rbx, %rdx
movq %r12, %rbx
callq 0x44b5
movq %r13, %r8
movq -0x48(%rbp), %rsi
movslq %eax, %r15
addq %r14, %r15
cmpq -0x30(%rbp), %r15
jb 0x49c8
movq %r8, %rdi
callq 0x2190
movq -0x40(%rbp), %rdi
callq 0x2190
movq %rbx, %rdi
callq 0x2190
cmpl $0x0, -0x38(%rbp)
js 0x4acf
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 0x653(%rip), %rsi       # 0x510a
movq %rax, %rdi
callq 0x2230
movq 0x351a(%rip), %rsi      # 0x7fe0
movq 0x3503(%rip), %rdx      # 0x7fd0
jmp 0x4af9
movl $0x10, %edi
callq 0x20a0
movq %rax, %rbx
leaq 0x645(%rip), %rsi       # 0x5128
movq %rax, %rdi
callq 0x2050
movq 0x34c6(%rip), %rsi      # 0x7fb8
movq 0x34b7(%rip), %rdx      # 0x7fb0
movq %rbx, %rdi
callq 0x21f0
jmp 0x4b03
movq %rax, %r14
movq %rbx, %rdi
callq 0x2100
movq %r14, %rdi
callq 0x2210