// File: toxaart[P]hierarchical_block_sparse_lib/source/HierarchicalBlockSparseMatrix.h
// Function: hbsm::HierarchicalBlockSparseMatrix<double>::add(hbsm::HierarchicalBlockSparseMatrix<double> const&, hbsm::HierarchicalBlockSparseMatrix<double> const&, hbsm::HierarchicalBlockSparseMatrix<double>&, unsigned long*)
void HierarchicalBlockSparseMatrix<Treal>::add(HierarchicalBlockSparseMatrix<Treal> const & A,
				       HierarchicalBlockSparseMatrix<Treal> const & B,
				       HierarchicalBlockSparseMatrix<Treal> & C,
					   size_t* no_of_resizes){

      if(!C.empty()) C.clear();

			if(A.empty() && B.empty()){
				return;
			}


			if(A.nRows_orig != B.nRows_orig || A.nCols_orig != B.nCols_orig ){
				throw std::runtime_error("Error in HierarchicalBlockSparseMatrix::add(): matrices to add have different sizes!");
			}

      C.set_params(A.get_params());

      C.resize(A.nRows_orig,A.nCols_orig, no_of_resizes);

			if(A.lowest_level()){


				int blocksize = A.blocksize;

				int noOfElements = blocksize*blocksize;
				Treal const ONEreal = 1.0;
				int  const ONEint  = 1;

				//copy A to C
				memcpy(&C.submatrix[0], &A.submatrix[0], sizeof(Treal) * noOfElements);

				// Add 1.0 * B to C.
				axpy(&noOfElements, &ONEreal, &B.submatrix[0], &ONEint, &C.submatrix[0], &ONEint);

				return;
			}

			for(int i = 0; i < 4; ++i){

				if(A.children[i] != NULL && B.children[i] != NULL){

					if(C.children[i] != NULL) throw std::runtime_error("Error in HierarchicalBlockSparseMatrix::add(): matrix C has non-null child!");


					C.children[i] = std::make_shared<HierarchicalBlockSparseMatrix<Treal> >();
					C.children[i]->parent = &C;

					add(*A.children[i], *B.children[i], *C.children[i], no_of_resizes);

				}

				if(A.children[i] == NULL && B.children[i] != NULL){

					if(C.children[i] != NULL) throw std::runtime_error("Error in HierarchicalBlockSparseMatrix::add(): matrix C has non-null child!");
					C.children[i] = B.children[i]; // smart pointer assignment. Now C.children[i] has parent in B, but it does not matter since they are of the  same size!

				}

				if(A.children[i] != NULL && B.children[i] == NULL){

					if(C.children[i] != NULL) throw std::runtime_error("Error in HierarchicalBlockSparseMatrix::add(): matrix C has non-null child!");
					C.children[i] = A.children[i]; // smart pointer assignment. Now C.children[i] has parent in A, but it does not matter since they are of the  same size!

				}

				if(A.children[i] == NULL && B.children[i] == NULL){

					if(C.children[i] != NULL) throw std::runtime_error("Error in HierarchicalBlockSparseMatrix::add(): matrix C has non-null child!");

					//nothing to do here, leave it NULL
				}

			}

			C.n_block_multiplies = A.get_n_block_multiplications() + B.get_n_block_multiplications();

			return;
		}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq -0x18(%rbp), %rdi
callq 0x230a0
testb $0x1, %al
jne 0x8f61
movq -0x18(%rbp), %rdi
callq 0x23300
movq -0x8(%rbp), %rdi
callq 0x230a0
testb $0x1, %al
jne 0x8f70
jmp 0x8f84
movq -0x10(%rbp), %rdi
callq 0x230a0
testb $0x1, %al
jne 0x8f7f
jmp 0x8f84
jmp 0x956e
movq -0x8(%rbp), %rax
movl 0x8(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0x8(%rcx), %eax
jne 0x8fa4
movq -0x8(%rbp), %rax
movl 0xc(%rax), %eax
movq -0x10(%rbp), %rcx
cmpl 0xc(%rcx), %eax
je 0x8ff7
movl $0x10, %edi
callq 0x20d0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x60(%rbp)
leaq 0x2dbe5(%rip), %rsi     # 0x36ba4
callq 0x20a0
jmp 0x8fc6
movq -0x60(%rbp), %rdi
movq 0x3801f(%rip), %rsi     # 0x40ff0
movq 0x37fe8(%rip), %rdx     # 0x40fc0
callq 0x2320
movq -0x60(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x2150
jmp 0x9577
movq -0x18(%rbp), %rax
movq %rax, -0x68(%rbp)
movq -0x8(%rbp), %rdi
callq 0x243e0
movq -0x68(%rbp), %rdi
movl %eax, -0x30(%rbp)
leaq -0x30(%rbp), %rsi
callq 0x8570
movq -0x18(%rbp), %rdi
movq -0x8(%rbp), %rax
movl 0x8(%rax), %esi
movq -0x8(%rbp), %rax
movl 0xc(%rax), %edx
movq -0x20(%rbp), %rcx
callq 0x8600
movq -0x8(%rbp), %rdi
callq 0x23500
testb $0x1, %al
jne 0x9045
jmp 0x90ed
movq -0x8(%rbp), %rax
movl 0x10(%rax), %eax
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
imull -0x34(%rbp), %eax
movl %eax, -0x38(%rbp)
movsd 0x2cfbf(%rip), %xmm0    # 0x36020
movsd %xmm0, -0x40(%rbp)
movl $0x1, -0x44(%rbp)
movq -0x18(%rbp), %rdi
addq $0x70, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x22b60
movq %rax, -0x78(%rbp)
movq -0x8(%rbp), %rdi
addq $0x70, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x245a0
movq -0x78(%rbp), %rdi
movq %rax, %rsi
movslq -0x38(%rbp), %rdx
shlq $0x3, %rdx
callq 0x21a0
movq -0x10(%rbp), %rdi
addq $0x70, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x245a0
movq %rax, -0x70(%rbp)
movq -0x18(%rbp), %rdi
addq $0x70, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x22b60
movq -0x70(%rbp), %rdx
movq %rax, %r8
leaq -0x38(%rbp), %rdi
leaq -0x40(%rbp), %rsi
leaq -0x44(%rbp), %r9
movq %r9, %rcx
callq 0x27330
jmp 0x956e
movl $0x0, -0x48(%rbp)
cmpl $0x4, -0x48(%rbp)
jge 0x9543
movq -0x8(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x232b0
testb $0x1, %al
jne 0x9123
jmp 0x9289
movq -0x10(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x232b0
testb $0x1, %al
jne 0x9148
jmp 0x9289
movq -0x18(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x232b0
testb $0x1, %al
jne 0x916a
jmp 0x91bd
movl $0x10, %edi
callq 0x20d0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x80(%rbp)
leaq 0x2da74(%rip), %rsi     # 0x36bf9
callq 0x20a0
jmp 0x918c
movq -0x80(%rbp), %rdi
movq 0x37e59(%rip), %rsi     # 0x40ff0
movq 0x37e22(%rip), %rdx     # 0x40fc0
callq 0x2320
movq -0x80(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x2150
jmp 0x9577
leaq -0x58(%rbp), %rdi
callq 0x245c0
movq -0x18(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
leaq -0x58(%rbp), %rsi
callq 0x235b0
leaq -0x58(%rbp), %rdi
callq 0x235e0
movq -0x18(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x18(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
callq 0x23570
movq -0x98(%rbp), %rcx
movq %rcx, 0x68(%rax)
movq -0x8(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
callq 0x24630
movq %rax, -0x90(%rbp)
movq -0x10(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
callq 0x24630
movq %rax, -0x88(%rbp)
movq -0x18(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
callq 0x24630
movq -0x90(%rbp), %rdi
movq -0x88(%rbp), %rsi
movq %rax, %rdx
movq -0x20(%rbp), %rcx
callq 0x8f30
movq -0x8(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x27380
testb $0x1, %al
jne 0x92ae
jmp 0x937c
movq -0x10(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x232b0
testb $0x1, %al
jne 0x92d3
jmp 0x937c
movq -0x18(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x232b0
testb $0x1, %al
jne 0x92f5
jmp 0x9351
movl $0x10, %edi
callq 0x20d0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xa0(%rbp)
leaq 0x2d8e6(%rip), %rsi     # 0x36bf9
callq 0x20a0
jmp 0x931a
movq -0xa0(%rbp), %rdi
movq 0x37cc8(%rip), %rsi     # 0x40ff0
movq 0x37c91(%rip), %rdx     # 0x40fc0
callq 0x2320
movq -0xa0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x2150
jmp 0x9577
movq -0x10(%rbp), %rsi
addq $0x28, %rsi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rsi
movq -0x18(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
callq 0x273b0
movq -0x8(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x232b0
testb $0x1, %al
jne 0x93a1
jmp 0x946f
movq -0x10(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x27380
testb $0x1, %al
jne 0x93c6
jmp 0x946f
movq -0x18(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x232b0
testb $0x1, %al
jne 0x93e8
jmp 0x9444
movl $0x10, %edi
callq 0x20d0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xa8(%rbp)
leaq 0x2d7f3(%rip), %rsi     # 0x36bf9
callq 0x20a0
jmp 0x940d
movq -0xa8(%rbp), %rdi
movq 0x37bd5(%rip), %rsi     # 0x40ff0
movq 0x37b9e(%rip), %rdx     # 0x40fc0
callq 0x2320
movq -0xa8(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x2150
jmp 0x9577
movq -0x8(%rbp), %rsi
addq $0x28, %rsi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rsi
movq -0x18(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
callq 0x273b0
movq -0x8(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x27380
testb $0x1, %al
jne 0x9494
jmp 0x9533
movq -0x10(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x27380
testb $0x1, %al
jne 0x94b6
jmp 0x9533
movq -0x18(%rbp), %rdi
addq $0x28, %rdi
movslq -0x48(%rbp), %rax
shlq $0x4, %rax
addq %rax, %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x232b0
testb $0x1, %al
jne 0x94d8
jmp 0x9531
movl $0x10, %edi
callq 0x20d0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0xb0(%rbp)
leaq 0x2d703(%rip), %rsi     # 0x36bf9
callq 0x20a0
jmp 0x94fd
movq -0xb0(%rbp), %rdi
movq 0x37ae5(%rip), %rsi     # 0x40ff0
movq 0x37aae(%rip), %rdx     # 0x40fc0
callq 0x2320
movq -0xb0(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x2150
jmp 0x9577
jmp 0x9533
jmp 0x9535
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x90f4
movq -0x8(%rbp), %rdi
callq 0x12850
movq %rax, -0xb8(%rbp)
movq -0x10(%rbp), %rdi
callq 0x12850
movq -0xb8(%rbp), %rcx
addq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, 0x20(%rax)
addq $0xc0, %rsp
popq %rbp
retq
movq -0x28(%rbp), %rdi
callq 0x2340