// File: /workspace/github_cpp_makefile_star2_O3/iZhangHui[P]CppPrimer/CH03_StringsVectorsAndArrays/examples/multidim.cc
// Function: main
int main()
{
	// array of size 3; each element is an array of 4 uninitailzed ints 
	int ia1[3][4];
	
	// array of size 10; each element is a 20-element array 
	// whose elements are arrays of 30 ints
	int arr[10][20][30] = {0}; // initialize all elements to 0
	
	// assigns the first element of arr to the last element 
	// in the last row of ia
	ia1[2][3] = arr[0][0][0];
	
	// binds row to the second four-element array in ia 
	int (&row)[4] = ia1[1];
	
	// three elements, each element is an array of size 4
	int ia2[3][4] = { 
	    {0, 1, 2, 3},   // initializers for the row indexed by 0
	    {4, 5, 6, 7},   // initializers for the row indexed by 1
	    {8, 9, 10, 11}  // initializers for the row indexed by 2
	};
	
	// equivalent initialization without the optional 
	// nested braces for each row
	int ia3[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
	
	// explicitly initialize only element 0 in each row
	int ia4[3][4] = {{ 0 }, { 4 }, { 8 }};
	
	// explicitly initialize row 0; the remaining elements 
	// are value initialized
	int ix[3][4] = {0, 3, 6, 9};
	
	// prints 9 0 0 
	cout << ix[0][3] << ' ' << ix[1][0] << ' ' << ix[2][0] << endl;
	
	constexpr size_t rowCnt = 3, colCnt = 4;
	int ia[rowCnt][colCnt];   // 12 uninitialized elements 
	
    // for each row
    for (size_t i = 0; i != rowCnt; ++i) {
        // for each column within the row
        for (size_t j = 0; j != colCnt; ++j) {
            // assign the element's positional index as its value
            ia[i][j] = i * colCnt + j;   
		}
	}

	// four ways to print the contents of ia
	// 1. using nested range for loops
	for (const auto &row : ia) // for every element in the outer array
		for (auto col : row)   // for every element in the inner array
			cout << col << endl; // print the element's value
    cout << ia[0][0] << ' ' << ia[2][3] << endl; // prints 0 11


	// 2. using pointers and a traditional for loop
	//    with pointer arithmetic to calculate the end pointers 
	for (auto p = ia; p != ia + rowCnt; ++p) {
		// q points to the first element of an array of four ints; 
		// that is, q points to an int
	    for (auto q = *p; q != *p + colCnt; ++q)
	         cout << *q << ' ';
		cout << endl;
	}
	
	// 3. using pointers and a traditional for loop
	//    with the library begin and end functions to manage the pointers
	for (auto p = begin(ia); p != end(ia); ++p) {
		// q points to the first element in an inner array
		for (auto q = begin(*p); q != end(*p); ++q)
			cout << *q << ' ';  // prints the int value to which q points
		cout << endl;
	}
	
	// 4. using a type alias to declare the loop control variable
	using int_array = int[4]; // new style type alias declaration 

	for (int_array *p = ia; p != ia + 3; ++p) {
	    for (int *q = *p; q != *p + 4; ++q)
	         cout << *q << ' ';
		cout << endl;
	}

	// alternative way to assign positional index to elements 
	// in a two-dimensional array
	int alt_ia[rowCnt][colCnt]; // 12 uninitialized elements 
	size_t cnt = 0;
	for (auto &row : alt_ia)    // for every element in the outer array
		for (auto &col : row) { // for every element in the inner array
			col = cnt;          // give this element the next value
			++cnt;              // increment cnt
		}
	// now print the value of the array
	for (const auto &row : alt_ia) // for every element in the outer array
		for (auto col : row)     // for every element in the inner array
			cout << col << endl;

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq 0x2de4(%rip), %rdi      # 0x3fd8
movl $0x9, %esi
callq 0x1090
movb $0x20, %r14b
leaq -0x90(%rbp), %rbx
movb %r14b, (%rbx)
movl $0x1, %edx
movq %rax, %rdi
movq %rbx, %rsi
callq 0x1070
xorl %r15d, %r15d
movq %rax, %rdi
xorl %esi, %esi
callq 0x1090
movb %r14b, (%rbx)
leaq -0x90(%rbp), %r14
movl $0x1, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0x1070
movq %rax, %rdi
xorl %esi, %esi
callq 0x1090
movq %rax, %rbx
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x1060
movsbl %al, %esi
movq %rbx, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1040
xorl %eax, %eax
movl $0x4, %ecx
movq %r15, %rdx
movl %edx, -0x90(%rbp,%rdx,4)
incq %rdx
decq %rcx
jne 0x1280
incq %rax
addq $0x4, %r15
cmpq $0x3, %rax
jne 0x1278
xorl %r12d, %r12d
movq 0x2d32(%rip), %rbx      # 0x3fd8
addq $0x10, %r12
xorl %r13d, %r13d
movl (%r14,%r13), %esi
movq %rbx, %rdi
callq 0x1090
movq %rax, %r15
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x1060
movsbl %al, %esi
movq %r15, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1040
addq $0x4, %r13
cmpq $0x10, %r13
jne 0x12ad
addq $0x10, %r14
cmpq $0x30, %r12
jne 0x12a6
leaq -0x90(%rbp), %r12
movl (%r12), %esi
movq %rbx, %rdi
callq 0x1090
leaq -0x60(%rbp), %r14
movb $0x20, (%r14)
movl $0x1, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0x1070
movl 0x2c(%r12), %esi
movq %rax, %rdi
callq 0x1090
movq %rax, %r15
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x1060
movsbl %al, %esi
movq %r15, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1040
xorl %r15d, %r15d
addq $0x10, %r15
xorl %r13d, %r13d
movl (%r12,%r13), %esi
movq %rbx, %rdi
callq 0x1090
movb $0x20, -0x60(%rbp)
movl $0x1, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0x1070
addq $0x4, %r13
cmpq $0x10, %r13
jne 0x1363
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x1060
movsbl %al, %esi
movq %rbx, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1040
addq $0x10, %r12
cmpq $0x30, %r15
jne 0x135c
leaq -0x90(%rbp), %r15
xorl %r12d, %r12d
leaq -0x60(%rbp), %r14
addq $0x10, %r12
xorl %r13d, %r13d
movl (%r15,%r13), %esi
movq %rbx, %rdi
callq 0x1090
movb $0x20, -0x60(%rbp)
movl $0x1, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0x1070
addq $0x4, %r13
cmpq $0x10, %r13
jne 0x13d3
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x1060
movsbl %al, %esi
movq %rbx, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1040
addq $0x10, %r15
cmpq $0x30, %r12
jne 0x13cc
leaq -0x90(%rbp), %r15
xorl %r12d, %r12d
leaq -0x60(%rbp), %r14
addq $0x10, %r12
xorl %r13d, %r13d
movl (%r15,%r13), %esi
movq %rbx, %rdi
callq 0x1090
movb $0x20, -0x60(%rbp)
movl $0x1, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0x1070
addq $0x4, %r13
cmpq $0x10, %r13
jne 0x1443
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x1060
movsbl %al, %esi
movq %rbx, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1040
addq $0x10, %r15
cmpq $0x30, %r12
jne 0x143c
xorl %eax, %eax
xorl %ecx, %ecx
addq $0x10, %rax
xorl %edx, %edx
movl %ecx, (%r14,%rdx)
incl %ecx
addq $0x4, %rdx
cmpq $0x10, %rdx
jne 0x14a8
addq $0x10, %r14
cmpq $0x30, %rax
jne 0x14a2
leaq -0x60(%rbp), %r15
xorl %r12d, %r12d
movq 0x2b08(%rip), %rbx      # 0x3fd8
addq $0x10, %r12
xorl %r13d, %r13d
movl (%r15,%r13), %esi
movq %rbx, %rdi
callq 0x1090
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x1060
movsbl %al, %esi
movq %r14, %rdi
callq 0x1030
movq %rax, %rdi
callq 0x1040
addq $0x4, %r13
cmpq $0x10, %r13
jne 0x14d7
addq $0x10, %r15
cmpq $0x30, %r12
jne 0x14d0
xorl %eax, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq