// File: matteotiziano[P]simple-wavelet/wavelet.cpp
// Function: Wavelet<double>::Wavedec(Matrix<double> const&, unsigned long) const
Decomposition2D<T> Wavelet<T>::Wavedec(const Matrix<T>& x, size_t num_levels) const {
  if (x.GetNumRows() < (1 << num_levels) || x.GetNumColumns() < (1 << num_levels)) {
    throw std::invalid_argument("Wavelet::Wavedec");
  }
  Decomposition2D<T> decomposition(num_levels);
  Matrix<T> a = x;
  for (size_t k = 0; k < num_levels; k++) {
    Matrix<T> ak, hk, vk, dk;
    Dwt(a, ak, hk, vk, dk);
    // Save approximation coefficients for next iteration
    a = ak;
    // Store subbands obtained at current level k to Decomposition object
    decomposition.SetDetcoef(dk, kDiagonalSubband, k);
    decomposition.SetDetcoef(vk, kVerticalSubband, k);
    decomposition.SetDetcoef(hk, kHorizontalSubband, k);
  }
  // Store final approximation
  decomposition.SetAppcoef(a);
  return decomposition;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x120, %rsp            # imm = 0x120
movq %rdi, -0x118(%rbp)
movq %rdi, %rax
movq %rax, -0x110(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x108(%rbp)
movq -0x18(%rbp), %rdi
callq 0xca40
movq -0x20(%rbp), %rcx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
movslq %ecx, %rcx
cmpq %rcx, %rax
jb 0x64f3
movq -0x18(%rbp), %rdi
callq 0xca60
movq -0x20(%rbp), %rcx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
movslq %ecx, %rcx
cmpq %rcx, %rax
jae 0x654f
movl $0x10, %edi
callq 0x20e0
movq %rax, %rdi
movq %rdi, %rax
movq %rax, -0x120(%rbp)
leaq 0xbcf9(%rip), %rsi      # 0x1220a
callq 0x2380
jmp 0x6518
movq -0x120(%rbp), %rdi
movq 0x13aba(%rip), %rsi     # 0x19fe0
movq 0x13a93(%rip), %rdx     # 0x19fc0
callq 0x2330
movq -0x120(%rbp), %rdi
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
callq 0x2170
jmp 0x677c
movq -0x118(%rbp), %rdi
movb $0x0, -0x2d(%rbp)
movq -0x20(%rbp), %rsi
callq 0x5270
movq -0x18(%rbp), %rsi
leaq -0x58(%rbp), %rdi
callq 0x3490
jmp 0x6572
movq $0x0, -0x60(%rbp)
movq -0x60(%rbp), %rax
cmpq -0x20(%rbp), %rax
jae 0x6722
leaq -0x88(%rbp), %rdi
callq 0xca00
jmp 0x6596
leaq -0xb0(%rbp), %rdi
callq 0xca00
jmp 0x65a4
leaq -0xd8(%rbp), %rdi
callq 0xca00
jmp 0x65b2
leaq -0x100(%rbp), %rdi
callq 0xca00
jmp 0x65c0
movq -0x108(%rbp), %rdi
leaq -0x58(%rbp), %rsi
leaq -0x88(%rbp), %rdx
leaq -0xb0(%rbp), %rcx
leaq -0xd8(%rbp), %r8
leaq -0x100(%rbp), %r9
callq 0x6790
jmp 0x65ee
leaq -0x58(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x5790
jmp 0x6600
movq -0x118(%rbp), %rdi
movq -0x60(%rbp), %rcx
leaq -0x100(%rbp), %rsi
xorl %edx, %edx
callq 0x5620
jmp 0x661b
movq -0x118(%rbp), %rdi
movq -0x60(%rbp), %rcx
leaq -0xd8(%rbp), %rsi
movl $0x1, %edx
callq 0x5620
jmp 0x6639
movq -0x118(%rbp), %rdi
movq -0x60(%rbp), %rcx
leaq -0xb0(%rbp), %rsi
movl $0x2, %edx
callq 0x5620
jmp 0x6657
leaq -0x100(%rbp), %rdi
callq 0xca20
leaq -0xd8(%rbp), %rdi
callq 0xca20
leaq -0xb0(%rbp), %rdi
callq 0xca20
leaq -0x88(%rbp), %rdi
callq 0xca20
movq -0x60(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x60(%rbp)
jmp 0x657a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
jmp 0x6770
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
jmp 0x6749
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
jmp 0x6714
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
jmp 0x6708
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
jmp 0x66fc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
leaq -0x100(%rbp), %rdi
callq 0xca20
leaq -0xd8(%rbp), %rdi
callq 0xca20
leaq -0xb0(%rbp), %rdi
callq 0xca20
leaq -0x88(%rbp), %rdi
callq 0xca20
jmp 0x6749
movq -0x118(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x57e0
jmp 0x6734
movb $0x1, -0x2d(%rbp)
leaq -0x58(%rbp), %rdi
callq 0xca20
testb $0x1, -0x2d(%rbp)
jne 0x6760
jmp 0x6754
leaq -0x58(%rbp), %rdi
callq 0xca20
jmp 0x6770
movq -0x118(%rbp), %rdi
callq 0x53e0
movq -0x110(%rbp), %rax
addq $0x120, %rsp            # imm = 0x120
popq %rbp
retq
movq -0x118(%rbp), %rdi
callq 0x53e0
movq -0x28(%rbp), %rdi
callq 0x2350
nopw %cs:(%rax,%rax)
nop