// File: /workspace/github_cpp_makefile_star2_O2/dsharlet[P]array/test/readme.cpp
// Function: nda::test_readme_body()
TEST(readme) {
  // Define a 3 dimensional shape, and an array of this shape.
  using my_3d_shape_type = shape<dim<>, dim<>, dim<>>;
  constexpr int width = 16;
  constexpr int height = 10;
  constexpr int depth = 3;
  my_3d_shape_type my_3d_shape(width, height, depth);
  array<int, my_3d_shape_type> my_array(my_3d_shape);

  // Access elements of this array.
  for (int z = 0; z < depth; z++) {
    for (int y = 0; y < height; y++) {
      for (int x = 0; x < width; x++) {
        my_array(x, y, z) = 5;
      }
    }
  }

  // Use for_each_value helper to access this array.
  my_array.for_each_value([](int& value) { value = 5; });

  // Use for_all_indices/for_each_index helper to access this array.
  for_all_indices(my_3d_shape, [&](int x, int y, int z) { my_array(x, y, z) = 5; });
  for_each_index(my_3d_shape, [&](my_3d_shape_type::index_type i) { my_array[i] = 5; });

  // This shows the default iteration order of for_all_indices.
  my_3d_shape_type my_shape(2, 2, 2);
  for_all_indices(
      my_shape, [](int x, int y, int z) { std::cout << x << ", " << y << ", " << z << std::endl; });
  // Output:
  // 0, 0, 0
  // 1, 0, 0
  // 0, 1, 0
  // 1, 1, 0
  // 0, 0, 1
  // 1, 0, 1
  // 0, 1, 1
  // 1, 1, 1

  // This shows the iteration order of for_all_indices with
  // a permutation.
  for_all_indices<2, 0, 1>(
      my_shape, [](int x, int y, int z) { std::cout << x << ", " << y << ", " << z << std::endl; });
  // Output:
  // 0, 0, 0
  // 0, 0, 1
  // 1, 0, 0
  // 1, 0, 1
  // 0, 1, 0
  // 0, 1, 1
  // 1, 1, 0
  // 1, 1, 1

  index_t y = 0;
  index_t z = 0;

  // Define a compile-time dense 3 dimensional shape.
  using my_dense_3d_shape_type =
      shape<dim</*Min=*/dynamic, /*Extent=*/dynamic, /*Stride=*/1>, dim<>, dim<>>;
  array<char, my_dense_3d_shape_type> my_dense_array({16, 3, 3});
  for (auto x : my_dense_array.x()) {
    // The compiler knows that each loop iteration accesses
    // elements that are contiguous in memory for contiguous x.
    my_dense_array(x, y, z) = 0;
  }

  // Define a matrix type with row, column indices.
  using matrix_shape = shape<dim<>, dense_dim<>>;
  array<double, matrix_shape> my_matrix({10, 4});
  for (auto i : my_matrix.i()) {
    for (auto j : my_matrix.j()) {
      // This loop ordering is efficient for this type.
      my_matrix(i, j) = 0.0;
    }
  }

  // Demonstrate slicing an array.
  // Slicing
  array_ref_of_rank<int, 2> channel1 = my_array(_, _, 1);
  array_ref_of_rank<int, 1> row4_channel2 = my_array(_, 4, 2);

  // Cropping
  array_ref_of_rank<int, 3> top_left = my_array(interval<>{0, 2}, interval<>{0, 4}, _);
  array_ref_of_rank<int, 2> center_channel0 = my_array(interval<>{1, 2}, interval<>{2, 4}, 0);

  assert_used(channel1);
  assert_used(row4_channel2);
  assert_used(top_left);
  assert_used(center_channel0);

  // Demonstrate iterating over an array in tiles using split.
  constexpr index_t x_split_factor = 3;
  const index_t y_split_factor = 5;
  for (auto yo : split(my_array.y(), y_split_factor)) {
    for (auto xo : split<x_split_factor>(my_array.x())) {
      auto tile = my_array(xo, yo, _);
      for (auto x : tile.x()) {
        // The compiler knows this loop has a fixed extent x_split_factor!
        tile(x, y, z) = x;
      }
    }
  }
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x378, %rsp            # imm = 0x378
leaq 0x80(%rsp), %r14
pushq $0x10
popq %rsi
pushq $0xa
popq %rdx
pushq $0x3
popq %rcx
movq %r14, %rdi
callq 0x10b74
leaq 0x1b0(%rsp), %rbx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x10b92
xorl %ebp, %ebp
cmpl $0x3, %ebp
je 0x68746
xorl %r14d, %r14d
cmpl $0xa, %r14d
je 0x68742
xorl %r15d, %r15d
cmpl $0x10, %r15d
je 0x6873d
movq %rbx, %rdi
movl %r15d, %esi
movl %r14d, %edx
movl %ebp, %ecx
callq 0x112c6
movl $0x5, (%rax)
incl %r15d
jmp 0x6871c
incl %r14d
jmp 0x68713
incl %ebp
jmp 0x6870b
leaq 0x1d0(%rsp), %rsi
movq -0x8(%rsi), %rbx
leaq 0xc8(%rsp), %rdi
callq 0x12237
testq %rbx, %rbx
je 0x6881e
movq 0x108(%rsp), %rax
movq 0xf0(%rsp), %rcx
movq 0xd0(%rsp), %rdx
movq 0xe8(%rsp), %rsi
xorl %edi, %edi
testq %rsi, %rsi
cmovleq %rdi, %rsi
movq 0x100(%rsp), %r8
testq %rdx, %rdx
cmovleq %rdi, %rdx
testq %r8, %r8
movl $0x0, %r9d
cmovgq %r8, %r9
movq 0xd8(%rsp), %r10
shlq $0x2, %r10
shlq $0x2, %rcx
leaq (,%rax,4), %r11
cmpq %rdx, %rdi
je 0x68841
movq %rbx, %r14
xorl %r15d, %r15d
cmpq %rsi, %r15
je 0x68816
movq %r9, %r12
movq %r14, %r13
cmpq $0x1, %rax
jne 0x687fb
leaq (%r14,%r8,4), %r12
movq %r14, %r13
cmpq %r12, %r13
jae 0x6880e
movl $0x5, (%r13)
addq $0x4, %r13
jmp 0x687e8
subq $0x1, %r12
jb 0x6880e
movl $0x5, (%r13)
addq %r11, %r13
jmp 0x687fb
addq %rcx, %r14
incq %r15
jmp 0x687d0
incq %rdi
addq %r10, %rbx
jmp 0x687c5
movq 0xe8(%rsp), %rax
imulq 0x100(%rsp), %rax
imulq 0xd0(%rsp), %rax
testq %rax, %rax
jg 0x68d75
movq 0x80(%rsp), %rbx
movq 0x88(%rsp), %rax
addq %rbx, %rax
movq %rax, 0x10(%rsp)
leaq 0x1b0(%rsp), %r14
cmpq 0x10(%rsp), %rbx
je 0x688b8
movq 0x98(%rsp), %r15
movq 0xa0(%rsp), %r13
addq %r15, %r13
cmpq %r13, %r15
je 0x688b3
movl 0xb0(%rsp), %ebp
movq 0xb8(%rsp), %r12
subq $0x1, %r12
jb 0x688ae
movq %r14, %rdi
movl %ebp, %esi
movl %r15d, %edx
movl %ebx, %ecx
callq 0x112c6
movl $0x5, (%rax)
incl %ebp
jmp 0x6888f
incq %r15
jmp 0x6887b
incq %rbx
jmp 0x68861
movq 0x80(%rsp), %r15
movq 0x88(%rsp), %rax
addq %r15, %rax
movq %rax, 0x18(%rsp)
leaq 0x1b0(%rsp), %rbx
leaq 0xc8(%rsp), %r14
cmpq 0x18(%rsp), %r15
je 0x68954
movq 0x98(%rsp), %r13
movq 0xa0(%rsp), %rax
addq %r13, %rax
movq %rax, 0x10(%rsp)
cmpq 0x10(%rsp), %r13
je 0x6894f
movq 0xb0(%rsp), %r12
movq 0xb8(%rsp), %rbp
subq $0x1, %rbp
jb 0x6894a
movq %r15, 0xc8(%rsp)
movq %r13, 0xd0(%rsp)
movq %r12, 0xd8(%rsp)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x6d18e
movl $0x5, (%rax)
incq %r12
jmp 0x68916
incq %r13
jmp 0x688ff
incq %r15
jmp 0x688e0
leaq 0x38(%rsp), %rdi
pushq $0x2
popq %rcx
movl %ecx, %esi
movl %ecx, %edx
callq 0x10b74
movq 0x38(%rsp), %rbx
movq 0x40(%rsp), %rax
addq %rbx, %rax
movq %rax, 0x18(%rsp)
movq 0x7964a(%rip), %r14     # 0xe1fc8
leaq 0x3c91c(%rip), %r15     # 0xa52a1
cmpq 0x18(%rsp), %rbx
je 0x689ff
movq 0x50(%rsp), %r12
movq 0x58(%rsp), %rax
addq %r12, %rax
movq %rax, 0x10(%rsp)
cmpq 0x10(%rsp), %r12
je 0x689fa
movl 0x68(%rsp), %ebp
movq 0x70(%rsp), %r13
subq $0x1, %r13
jb 0x689f5
movq %r14, %rdi
movl %ebp, %esi
callq 0x22e0
movq %rax, %rdi
movq %r15, %rsi
callq 0x21c0
movq %rax, %rdi
movl %r12d, %esi
callq 0x22e0
movq %rax, %rdi
movq %r15, %rsi
callq 0x21c0
movq %rax, %rdi
movl %ebx, %esi
callq 0x22e0
movq %rax, %rdi
callq 0x20a0
incl %ebp
jmp 0x689ae
incq %r12
jmp 0x6899e
incq %rbx
jmp 0x68985
movl 0x38(%rsp), %eax
movl %eax, 0x18(%rsp)
movq 0x40(%rsp), %rax
movq %rax, 0x30(%rsp)
movq 0x68(%rsp), %rax
movq 0x50(%rsp), %rbx
movq 0x58(%rsp), %rcx
addq %rbx, %rcx
movq %rcx, 0x28(%rsp)
movq 0x70(%rsp), %rcx
movq %rax, 0x20(%rsp)
addq %rax, %rcx
movq %rcx, 0x10(%rsp)
movq 0x79587(%rip), %r14     # 0xe1fc8
leaq 0x3c859(%rip), %r15     # 0xa52a1
cmpq 0x28(%rsp), %rbx
je 0x68ab5
movq 0x20(%rsp), %r12
cmpq 0x10(%rsp), %r12
je 0x68ab0
movq 0x30(%rsp), %r13
movl 0x18(%rsp), %ebp
subq $0x1, %r13
jb 0x68aab
movq %r14, %rdi
movl %r12d, %esi
callq 0x22e0
movq %rax, %rdi
movq %r15, %rsi
callq 0x21c0
movq %rax, %rdi
movl %ebx, %esi
callq 0x22e0
movq %rax, %rdi
movq %r15, %rsi
callq 0x21c0
movq %rax, %rdi
movl %ebp, %esi
callq 0x22e0
movq %rax, %rdi
callq 0x20a0
incl %ebp
jmp 0x68a64
incq %r12
jmp 0x68a54
incq %rbx
jmp 0x68a48
leaq 0x160(%rsp), %rdi
pushq $0x10
popq %rsi
pushq $0x3
popq %rcx
movl %ecx, %edx
callq 0x10810
leaq 0xc8(%rsp), %rdi
leaq 0x160(%rsp), %rsi
callq 0x6a648
leaq 0xc8(%rsp), %rbx
movq 0x50(%rbx), %r14
movq 0x58(%rbx), %r15
subq $0x1, %r15
jb 0x68b0c
movq %rbx, %rdi
movq %r14, %rsi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x6a674
movb $0x0, (%rax)
incq %r14
jmp 0x68aef
leaq 0x268(%rsp), %rdi
pushq $0xa
popq %rsi
pushq $0x4
popq %rdx
callq 0x66cac
leaq 0x160(%rsp), %rdi
leaq 0x268(%rsp), %rsi
callq 0x6a688
movq 0x188(%rsp), %rax
movq 0x198(%rsp), %rcx
movq 0x1a0(%rsp), %rdx
addq %rcx, %rdx
xorl %esi, %esi
cmpq %rdx, %rcx
je 0x68b85
movq 0x1a8(%rsp), %rdi
imulq %rsi, %rdi
addq 0x178(%rsp), %rdi
xorl %r8d, %r8d
cmpq %r8, %rax
je 0x68b7c
andq $0x0, (%rdi,%r8,8)
incq %r8
jmp 0x68b6d
incq %rcx
addq $0x8, %rsi
jmp 0x68b51
leaq 0x2f0(%rsp), %rdi
leaq 0x1b0(%rsp), %rsi
pushq $0x1
popq %rdx
callq 0x6a6be
leaq 0x248(%rsp), %rdi
leaq 0x1b0(%rsp), %rsi
pushq $0x4
popq %rdx
pushq $0x2
popq %rcx
callq 0x6a6ea
leaq 0x268(%rsp), %rdi
leaq 0x1b0(%rsp), %rsi
pushq $0x2
popq %rcx
pushq $0x4
popq %r9
xorl %edx, %edx
xorl %r8d, %r8d
callq 0x6a71e
andl $0x0, (%rsp)
leaq 0x2b8(%rsp), %rdi
leaq 0x1b0(%rsp), %rsi
pushq $0x1
popq %rdx
pushq $0x2
popq %rcx
pushq $0x4
popq %r9
movq %rcx, %r8
callq 0x6a75a
leaq 0x2f0(%rsp), %rdi
callq 0x6a7a0
leaq 0x248(%rsp), %rdi
callq 0x6a7a1
leaq 0x268(%rsp), %rdi
callq 0x6a7a2
leaq 0x2b8(%rsp), %rdi
callq 0x6a7a0
leaq 0x200(%rsp), %rcx
movq -0x10(%rcx), %rsi
cmpq $0x5, %rsi
pushq $0x5
popq %rax
cmovlq %rsi, %rax
movq -0x18(%rcx), %rcx
leaq (%rsi,%rcx), %rdx
decq %rdx
addq %rcx, %rsi
movq %rsi, 0x10(%rsp)
leaq 0x148(%rsp), %rsi
movq %rcx, (%rsi)
movq %rax, 0x8(%rsi)
movq %rdx, 0x10(%rsi)
leaq 0x328(%rsp), %r12
movq 0x148(%rsp), %rbx
cmpq 0x10(%rsp), %rbx
je 0x68d3c
movq 0x150(%rsp), %r15
leaq 0x218(%rsp), %rdi
leaq 0x200(%rsp), %rsi
callq 0x6a7a3
movq 0x228(%rsp), %rax
movq %rax, 0x140(%rsp)
movups 0x218(%rsp), %xmm0
movaps %xmm0, 0x130(%rsp)
movq 0x230(%rsp), %r13
movq 0x130(%rsp), %rdx
cmpq %r13, %rdx
je 0x68d2a
movq %r12, %rdi
leaq 0x1b0(%rsp), %rsi
movq %rbx, %rcx
movq %r15, %r8
callq 0x6a7c2
movq 0x360(%rsp), %r14
pushq $0x3
popq %rbp
subq $0x1, %rbp
jb 0x68d1b
movq %r12, %rdi
movq %r14, %rsi
xorl %edx, %edx
xorl %ecx, %ecx
callq 0x6a7fa
movl %r14d, (%rax)
incq %r14
jmp 0x68cfe
leaq 0x130(%rsp), %rdi
callq 0x6a80e
jmp 0x68cd0
leaq 0x148(%rsp), %rdi
callq 0x6a816
jmp 0x68c78
leaq 0x160(%rsp), %rdi
callq 0x6a81e
leaq 0xc8(%rsp), %rdi
callq 0x6a82e
leaq 0x1b0(%rsp), %rdi
callq 0x10d02
addq $0x378, %rsp            # imm = 0x378
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x24513(%rip), %rdi     # 0x8d28f
leaq 0x2434e(%rip), %rsi     # 0x8d0d1
leaq 0x3ef42(%rip), %rcx     # 0xa7ccc
movl $0x6a1, %edx            # imm = 0x6A1
callq 0x20e0
jmp 0x68db1
jmp 0x68db1
jmp 0x68db1
jmp 0x68db1
jmp 0x68dd8
jmp 0x68dd8
jmp 0x68da8
jmp 0x68dd8
jmp 0x68db1
jmp 0x68db1
movq %rax, %rbx
jmp 0x68dc1
jmp 0x68db1
jmp 0x68db1
movq %rax, %rbx
leaq 0x160(%rsp), %rdi
callq 0x6a81e
leaq 0xc8(%rsp), %rdi
callq 0x6a82e
jmp 0x68ddb
jmp 0x68dd8
jmp 0x68dd8
jmp 0x68dd8
jmp 0x68dd8
movq %rax, %rbx
leaq 0x1b0(%rsp), %rdi
callq 0x10d02
movq %rbx, %rdi
callq 0x22f0