// File: /workspace/github_c_makefile_star2_O2/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, %ebx
leaq 0x48(%rsp), %rdi
xorl %esi, %esi
callq 0x1060
cmpl $0x7, %ebx
jne 0x156f
movq 0x48(%rsp), %rax
movq %rax, 0x10(%rsp)
movq 0x50(%rsp), %rax
movq %rax, 0x20(%rsp)
leaq 0xdcd(%rip), %r12       # 0x202c
pushq $0x7
popq %rbp
leaq 0xdaf(%rip), %rbx       # 0x2018
movq 0x2d80(%rip), %r15      # 0x3ff0
movl %ebp, %edi
movq %r14, %rsi
movq %r12, %rdx
callq 0x1080
leal -0x3f(%rax), %ecx
cmpl $0x4, %ecx
ja 0x1293
movslq (%rbx,%rcx,4), %rax
addq %rbx, %rax
jmpq *%rax
movq (%r15), %r13
jmp 0x1270
cmpl $-0x1, %eax
jne 0x1270
jmp 0x12ae
movq (%r15), %rax
movq %rax, 0x8(%rsp)
jmp 0x1270
movq (%r15), %rax
movq %rax, 0x60(%rsp)
jmp 0x1270
leaq 0x1c(%rsp), %rsi
leaq 0x34(%rsp), %r14
leaq 0x40(%rsp), %rcx
movq %r13, %rdi
movq %r14, %rdx
callq 0x1735
leaq 0x30(%rsp), %r12
leaq 0x18(%rsp), %rdx
leaq 0x38(%rsp), %rcx
movq 0x8(%rsp), %rdi
movq %r12, %rsi
callq 0x1735
movl (%r14), %eax
cmpl (%r12), %eax
jne 0x1578
movslq 0x1c(%rsp), %rdi
movslq 0x18(%rsp), %r12
movq %rdi, 0x58(%rsp)
imulq %r12, %rdi
shlq $0x3, %rdi
callq 0x1090
movq %rax, %r14
xorl %ebp, %ebp
leaq 0x48(%rsp), %r13
movq %r13, %rdi
xorl %esi, %esi
callq 0x1060
movq (%r13), %rax
movq %rax, 0x8(%rsp)
movq 0x8(%r13), %rax
movq %rax, 0x28(%rsp)
movl 0x1c(%rsp), %edx
movslq 0x18(%rsp), %rsi
movl 0x30(%rsp), %edi
movq 0x40(%rsp), %r8
movslq 0x34(%rsp), %r9
testl %edi, %edi
cmovlel %ebp, %edi
testl %esi, %esi
movl $0x0, %r10d
cmovgl %esi, %r10d
movq 0x38(%rsp), %rcx
testl %edx, %edx
cmovlel %ebp, %edx
shlq $0x3, %r9
shlq $0x3, %rsi
xorpd %xmm3, %xmm3
movsd 0xc8f(%rip), %xmm0      # 0x2008
cmpq %rdx, %rbp
je 0x13d4
movq %rbp, %rax
imulq %r12, %rax
leaq (%r14,%rax,8), %rbx
movq %rcx, %r11
xorl %eax, %eax
cmpq %r10, %rax
je 0x13cc
xorpd %xmm1, %xmm1
movq %r11, %r13
xorl %r15d, %r15d
cmpq %r15, %rdi
je 0x13be
movsd (%r8,%r15,8), %xmm2
mulsd (%r13), %xmm2
addsd %xmm2, %xmm1
addsd %xmm0, %xmm3
incq %r15
addq %rsi, %r13
jmp 0x139d
movsd %xmm1, (%rbx,%rax,8)
incq %rax
addq $0x8, %r11
jmp 0x138e
incq %rbp
addq %r9, %r8
jmp 0x1379
cvtsi2sdq 0x8(%rsp), %xmm0
cvtsi2sdq 0x28(%rsp), %xmm2
movsd 0xc26(%rip), %xmm1      # 0x2010
divsd %xmm1, %xmm2
addsd %xmm0, %xmm2
movsd %xmm2, 0x8(%rsp)
cvtsi2sdq 0x10(%rsp), %xmm0
cvtsi2sdq 0x20(%rsp), %xmm2
divsd %xmm1, %xmm2
addsd %xmm0, %xmm2
movsd %xmm2, 0x28(%rsp)
leaq 0x48(%rsp), %r13
movq %r13, %rdi
xorl %esi, %esi
movsd %xmm3, 0x20(%rsp)
callq 0x1060
cvtsi2sdq (%r13), %xmm0
cvtsi2sdq 0x8(%r13), %xmm1
divsd 0xbd3(%rip), %xmm1      # 0x2010
addsd %xmm0, %xmm1
movsd %xmm1, 0x10(%rsp)
movq 0x60(%rsp), %rdi
movq 0x58(%rsp), %rsi
movl %r12d, %edx
movq %r14, %rcx
callq 0x16b3
movq 0x40(%rsp), %rdi
callq 0x10b0
movq 0x38(%rsp), %rdi
callq 0x10b0
movq %r14, %rdi
callq 0x10b0
leaq 0x48(%rsp), %rbx
movq %rbx, %rdi
xorl %esi, %esi
callq 0x1060
cvtsi2sdq (%rbx), %xmm0
cvtsi2sdq 0x8(%rbx), %xmm1
movsd 0xb76(%rip), %xmm3      # 0x2010
divsd %xmm3, %xmm1
addsd %xmm0, %xmm1
movsd 0x10(%rsp), %xmm2
subsd %xmm2, %xmm1
movsd 0x8(%rsp), %xmm0
subsd %xmm0, %xmm2
movsd %xmm2, 0x10(%rsp)
subsd 0x28(%rsp), %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, 0x8(%rsp)
movsd 0x20(%rsp), %xmm0
divsd %xmm3, %xmm0
movsd %xmm0, 0x20(%rsp)
movl 0x1c(%rsp), %esi
movl 0x18(%rsp), %edx
leaq 0xb48(%rip), %rdi       # 0x2033
xorl %eax, %eax
callq 0x1030
leaq 0xb48(%rip), %rdi       # 0x2041
movsd 0x8(%rsp), %xmm0
movb $0x1, %al
callq 0x1030
leaq 0xb4d(%rip), %rdi       # 0x205a
movsd 0x10(%rsp), %xmm0
movb $0x1, %al
callq 0x1030
movsd 0x8(%rsp), %xmm0
addsd 0x10(%rsp), %xmm0
movsd %xmm0, 0x8(%rsp)
leaq 0xb3f(%rip), %rdi       # 0x2072
movb $0x1, %al
callq 0x1030
movsd 0x20(%rsp), %xmm1
movapd %xmm1, %xmm0
divsd 0x10(%rsp), %xmm0
divsd 0x8(%rsp), %xmm1
leaq 0xb30(%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 0xb77(%rip), %rdi       # 0x20ed
jmp 0x157f
leaq 0xb39(%rip), %rdi       # 0x20b8
callq 0x1040
pushq $0x1
popq %rdi
callq 0x1050