// File: /workspace/github_c_makefile_star2_O1/baileywjohnson[P]mpi-matrix-mult/mm-serial.c
// Function: main
int main(int argc, char *argv[]){

	double io_start_1 = 0;
	GET_TIME(io_start_1);

	double *A;
	int a_rows, a_columns;
	double *B;
	int b_rows, b_columns;
	double *C;
	int c_rows, c_columns;

	char *a_in;
	char *b_in;
	char *c_out;

	int c;
	if(argc != 7){
		printf("USAGE: mm-serial -A <matrix 1 filename> -B <matrix 2 filename> -C <output filename>\n");
		exit(1);
	}
	while((c = getopt(argc, argv, "A:B:C:")) != -1){
		switch(c){
			case 'A':
				a_in = optarg;
				break;
			case 'B':
				b_in = optarg;
				break;
			case 'C':
				c_out = optarg;
				break;
			case '?':
				exit(1);
				break;
			default:
				break;
		}
	}

	read_matrix(a_in, &a_rows, &a_columns, &A);
	read_matrix(b_in, &b_rows, &b_columns, &B);

	if(a_columns != b_rows){
		printf("Matrices provided not compatible for multiplication.\n");
		exit(1);
	}

	c_rows = a_rows;
	c_columns = b_columns;
	C = malloc(sizeof(double) * (c_rows * c_columns));

	double io_finish_1 = 0;
	GET_TIME(io_finish_1);

	double flops = 0;

	int i, j, count;
	for(i = 0; i < a_rows; i++){
		count = 0;
		while(count < b_columns){
			double result = 0;
			for(j = 0; j < b_rows; j++){
				result += A[(i * a_columns) + j] * B[(j * b_columns) + count];
				flops += 1;
			}
			C[(c_columns * i) + count] = result;
			count += 1;
		}
	}	
	
	double io_start_2 = 0;
	GET_TIME(io_start_2);

	write_matrix(c_out, c_rows, c_columns, C);	

	free(A);
	free(B);
	free(C);

	double io_finish_2 = 0;
	GET_TIME(io_finish_2);

	double io_time = (io_finish_2 - io_start_2) + (io_finish_1 - io_start_1);
	double mm_time = (io_start_2 - io_finish_1);
	double mflop_count = flops/1000000;
	printf("M: %i, N: %i\n", a_rows, b_columns);
	printf("Time Doing I/O: %f sec.\n", io_time);
	printf("Time Doing MM: %f sec.\n", mm_time);
	printf("Total Time: %f sec.\n", io_time + mm_time);
	printf("MFlops (without I/O): %e, MFlops (with I/O): %e\n", mflop_count/mm_time, mflop_count/(io_time + mm_time));

	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x68, %rsp
movq %rsi, %r14
movl %edi, %ebp
leaq 0x40(%rsp), %rdi
xorl %esi, %esi
callq 0x1060
cmpl $0x7, %ebp
jne 0x1578
movq 0x40(%rsp), %rax
movq %rax, 0x8(%rsp)
movq 0x48(%rsp), %rax
movq %rax, 0x18(%rsp)
leaq 0xdcd(%rip), %r12       # 0x202c
leaq 0xdb2(%rip), %rbx       # 0x2018
movq 0x2d83(%rip), %r15      # 0x3ff0
movl %ebp, %edi
movq %r14, %rsi
movq %r12, %rdx
callq 0x1080
leal -0x3f(%rax), %ecx
cmpl $0x4, %ecx
ja 0x1290
movslq (%rbx,%rcx,4), %rax
addq %rbx, %rax
jmpq *%rax
movq (%r15), %r13
jmp 0x126d
cmpl $-0x1, %eax
jne 0x126d
jmp 0x12aa
movq (%r15), %rax
movq %rax, (%rsp)
jmp 0x126d
movq (%r15), %rax
movq %rax, 0x60(%rsp)
jmp 0x126d
leaq 0x14(%rsp), %rsi
leaq 0x2c(%rsp), %r14
leaq 0x38(%rsp), %rcx
movq %r13, %rdi
movq %r14, %rdx
callq 0x173b
leaq 0x28(%rsp), %r12
leaq 0x10(%rsp), %rdx
leaq 0x30(%rsp), %rcx
movq (%rsp), %rdi
movq %r12, %rsi
callq 0x173b
movl (%r14), %eax
cmpl (%r12), %eax
jne 0x1581
movslq 0x14(%rsp), %rdi
movslq 0x10(%rsp), %r12
movq %rdi, 0x58(%rsp)
imulq %r12, %rdi
shlq $0x3, %rdi
callq 0x1090
movq %rax, %r14
leaq 0x40(%rsp), %r13
movq %r13, %rdi
xorl %esi, %esi
callq 0x1060
movq (%r13), %rax
movq %rax, (%rsp)
movq 0x8(%r13), %rax
movq %rax, 0x50(%rsp)
movslq 0x14(%rsp), %rdx
testq %rdx, %rdx
jle 0x13c9
movl 0x10(%rsp), %esi
movl 0x28(%rsp), %edi
movq 0x38(%rsp), %r8
movslq 0x2c(%rsp), %r9
movq 0x30(%rsp), %rcx
movslq %esi, %r11
shlq $0x3, %r9
shlq $0x3, %r11
xorpd %xmm3, %xmm3
xorl %r13d, %r13d
movsd 0xc9e(%rip), %xmm0      # 0x2008
testl %esi, %esi
jle 0x13bc
movq %r13, %rax
imulq %r12, %rax
leaq (%r14,%rax,8), %rbp
movq %rcx, %rbx
xorl %eax, %eax
xorpd %xmm1, %xmm1
testl %edi, %edi
jle 0x13aa
movq %rbx, %r10
xorl %r15d, %r15d
movsd (%r8,%r15,8), %xmm2
mulsd (%r10), %xmm2
addsd %xmm2, %xmm1
addsd %xmm0, %xmm3
incq %r15
addq %r11, %r10
cmpq %r15, %rdi
jne 0x138c
movsd %xmm1, (%rbp,%rax,8)
incq %rax
addq $0x8, %rbx
cmpq %rsi, %rax
jne 0x137e
incq %r13
addq %r9, %r8
cmpq %rdx, %r13
jne 0x136a
jmp 0x13cd
xorpd %xmm3, %xmm3
movsd %xmm3, 0x20(%rsp)
xorps %xmm0, %xmm0
cvtsi2sdq (%rsp), %xmm0
xorps %xmm2, %xmm2
cvtsi2sdq 0x50(%rsp), %xmm2
movsd 0xc22(%rip), %xmm1      # 0x2010
divsd %xmm1, %xmm2
addsd %xmm0, %xmm2
movsd %xmm2, (%rsp)
xorps %xmm0, %xmm0
cvtsi2sdq 0x8(%rsp), %xmm0
xorps %xmm2, %xmm2
cvtsi2sdq 0x18(%rsp), %xmm2
divsd %xmm1, %xmm2
addsd %xmm0, %xmm2
movsd %xmm2, 0x18(%rsp)
leaq 0x40(%rsp), %r13
movq %r13, %rdi
xorl %esi, %esi
callq 0x1060
xorps %xmm0, %xmm0
cvtsi2sdq (%r13), %xmm0
xorps %xmm1, %xmm1
cvtsi2sdq 0x8(%r13), %xmm1
divsd 0xbca(%rip), %xmm1      # 0x2010
addsd %xmm0, %xmm1
movsd %xmm1, 0x8(%rsp)
movq 0x60(%rsp), %rdi
movq 0x58(%rsp), %rsi
movl %r12d, %edx
movq %r14, %rcx
callq 0x16ba
movq 0x38(%rsp), %rdi
callq 0x10b0
movq 0x30(%rsp), %rdi
callq 0x10b0
movq %r14, %rdi
callq 0x10b0
leaq 0x40(%rsp), %rbx
movq %rbx, %rdi
xorl %esi, %esi
callq 0x1060
xorps %xmm0, %xmm0
cvtsi2sdq (%rbx), %xmm0
xorps %xmm1, %xmm1
cvtsi2sdq 0x8(%rbx), %xmm1
movsd 0xb67(%rip), %xmm3      # 0x2010
divsd %xmm3, %xmm1
addsd %xmm0, %xmm1
movsd 0x8(%rsp), %xmm2
subsd %xmm2, %xmm1
movsd (%rsp), %xmm0
subsd %xmm0, %xmm2
movsd %xmm2, 0x8(%rsp)
subsd 0x18(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, (%rsp)
movsd 0x20(%rsp), %xmm0
divsd %xmm3, %xmm0
movsd %xmm0, 0x20(%rsp)
movl 0x14(%rsp), %esi
movl 0x10(%rsp), %edx
leaq 0xb3b(%rip), %rdi       # 0x2033
xorl %eax, %eax
callq 0x1030
leaq 0xb3b(%rip), %rdi       # 0x2041
movsd (%rsp), %xmm0
movb $0x1, %al
callq 0x1030
leaq 0xb41(%rip), %rdi       # 0x205a
movsd 0x8(%rsp), %xmm0
movb $0x1, %al
callq 0x1030
movsd (%rsp), %xmm0
addsd 0x8(%rsp), %xmm0
movsd %xmm0, (%rsp)
leaq 0xb35(%rip), %rdi       # 0x2072
movb $0x1, %al
callq 0x1030
movsd 0x20(%rsp), %xmm1
movapd %xmm1, %xmm0
divsd 0x8(%rsp), %xmm0
divsd (%rsp), %xmm1
leaq 0xb27(%rip), %rdi       # 0x2087
movb $0x2, %al
callq 0x1030
xorl %eax, %eax
addq $0x68, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0xb6e(%rip), %rdi       # 0x20ed
jmp 0x1588
leaq 0xb30(%rip), %rdi       # 0x20b8
callq 0x1040
movl $0x1, %edi
callq 0x1050
nop