// File: /workspace/github_cpp_makefile_star2_O2/dsharlet[P]array/test/image.cpp
// Function: void nda::test_copy<int, nda::shape<nda::dim<-9l, -9l, 1l>, nda::dim<-9l, -9l, -9l>, nda::dim<0l, 1l, 1l>>, nda::shape<nda::dim<-9l, -9l, 1l>, nda::dim<-9l, -9l, -9l>, nda::dim<0l, 1l, 1l>>>(long)
void test_copy(index_t channels) {
  array<T, ShapeSrc> src({40, 30, channels});
  fill_pattern(src);

  array<T, ShapeDest> dest({src.width(), src.height(), channels});
  copy(src, dest);
  check_pattern(dest);

  array<T, ShapeDest> dest_cropped({{5, 30}, {3, 20}, channels});
  copy(src, dest);
  check_pattern(dest);

  // If the src and dest shapes are the same, we should expect copies
  // to be about as fast as memcpy, even if the dest is cropped (so
  // some cleverness is required to copy rows at a time).
  // TODO: It would be nice if this were fast even for different shapes.
  // This may be impossible on x86. On ARM, using vstN/vldN, it may
  // be possible, but we need to find a way to sort dimensions by stride
  // while preserving the compile time constant extent.
#if 0
  if (std::is_same<ShapeSrc, ShapeDest>::value) {
    double copy_time = benchmark([&]() {
      copy(src, dest_cropped);
    });
    check_pattern(dest_cropped);

    array<T, ShapeDest> dest_memcpy(dest_cropped.shape());
    double memcpy_time = benchmark([&]() {
      std::memcpy(dest_memcpy.base(), src.base(), dest_cropped.size() * sizeof(T));
    });
    // This memcpy is *not* correct, but the performance of it
    // is optimistic.
    ASSERT(dest_memcpy != dest_cropped);

    ASSERT_LT(copy_time, memcpy_time * 1.2);
  }
#endif
}

// Assembly:
pushq %r15
pushq %r14
pushq %rbx
subq $0x190, %rsp            # imm = 0x190
movq %rdi, %rbx
leaq 0x40(%rsp), %r14
pushq $0x28
popq %rsi
pushq $0x1e
popq %rdx
movq %r14, %rdi
movq %rbx, %rcx
callq 0x53d44
leaq 0x98(%rsp), %r15
movq %r15, %rdi
movq %r14, %rsi
callq 0x514d2
movq %r15, %rdi
xorl %esi, %esi
callq 0x53d63
movq 0xc8(%rsp), %rdx
movq 0xe0(%rsp), %rsi
leaq 0xf0(%rsp), %rdi
movq %rbx, %rcx
callq 0x53da0
leaq 0x40(%rsp), %rdi
leaq 0xf0(%rsp), %rsi
callq 0x514d2
leaq 0x98(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x53dbf
xorps %xmm0, %xmm0
leaq 0xf0(%rsp), %rsi
movaps %xmm0, (%rsi)
andq $0x0, 0x10(%rsi)
leaq 0x40(%rsp), %rdi
callq 0x53e31
movq $0x5, 0x28(%rsp)
movq $0x1e, 0x30(%rsp)
movq $0x3, 0x10(%rsp)
movq $0x14, 0x18(%rsp)
movabsq $-0x8000000000000000, %rax # imm = 0x8000000000000000
movq %rax, 0x20(%rsp)
leaq 0xd(%rsp), %rdi
movq %rbx, %rsi
callq 0x53e6e
leaq 0x150(%rsp), %rdi
leaq 0x28(%rsp), %rsi
leaq 0x10(%rsp), %rdx
leaq 0xd(%rsp), %rcx
callq 0x51466
leaq 0xf0(%rsp), %rdi
leaq 0x150(%rsp), %rsi
callq 0x514d2
leaq 0x98(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x53dbf
xorps %xmm0, %xmm0
leaq 0x150(%rsp), %rsi
movaps %xmm0, (%rsi)
andq $0x0, 0x10(%rsi)
leaq 0x40(%rsp), %rdi
callq 0x53e31
leaq 0xf0(%rsp), %rdi
callq 0x51510
leaq 0x40(%rsp), %rdi
callq 0x51510
leaq 0x98(%rsp), %rdi
callq 0x51510
addq $0x190, %rsp            # imm = 0x190
popq %rbx
popq %r14
popq %r15
retq
jmp 0x5399a
movq %rax, %rbx
leaq 0xf0(%rsp), %rdi
callq 0x51510
jmp 0x539ba
jmp 0x539b7
jmp 0x539b7
jmp 0x539b2
movq %rax, %rbx
jmp 0x539c4
movq %rax, %rbx
leaq 0x40(%rsp), %rdi
callq 0x51510
leaq 0x98(%rsp), %rdi
callq 0x51510
movq %rbx, %rdi
callq 0x22f0