// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x100, %rsp            # imm = 0x100
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x18(%rbp)
leaq -0x28(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1050
cvtsi2sdq -0x28(%rbp), %xmm0
cvtsi2sdq -0x20(%rbp), %xmm1
movsd 0xdc6(%rip), %xmm2      # 0x2008
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, -0x18(%rbp)
cmpl $0x7, -0x8(%rbp)
je 0x126d
leaq 0xdd0(%rip), %rdi       # 0x202c
movb $0x0, %al
callq 0x1030
movl $0x1, %edi
callq 0x1040
jmp 0x126f
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0xe04(%rip), %rdx       # 0x2081
callq 0x1060
movl %eax, -0x74(%rbp)
cmpl $-0x1, %eax
je 0x12f6
movl -0x74(%rbp), %eax
addl $-0x3f, %eax
movl %eax, %ecx
movq %rcx, -0x100(%rbp)
subl $0x4, %eax
ja 0x12ef
movq -0x100(%rbp), %rax
leaq 0xd6c(%rip), %rcx       # 0x2018
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x2d34(%rip), %rax      # 0x3ff0
movq (%rax), %rax
movq %rax, -0x60(%rbp)
jmp 0x12f1
movq 0x2d24(%rip), %rax      # 0x3ff0
movq (%rax), %rax
movq %rax, -0x68(%rbp)
jmp 0x12f1
movq 0x2d14(%rip), %rax      # 0x3ff0
movq (%rax), %rax
movq %rax, -0x70(%rbp)
jmp 0x12f1
movl $0x1, %edi
callq 0x1040
jmp 0x12f1
jmp 0x126f
movq -0x60(%rbp), %rdi
leaq -0x34(%rbp), %rsi
leaq -0x38(%rbp), %rdx
leaq -0x30(%rbp), %rcx
callq 0x1870
movq -0x68(%rbp), %rdi
leaq -0x44(%rbp), %rsi
leaq -0x48(%rbp), %rdx
leaq -0x40(%rbp), %rcx
callq 0x1870
movl -0x38(%rbp), %eax
cmpl -0x44(%rbp), %eax
je 0x1340
leaq 0xd59(%rip), %rdi       # 0x2088
movb $0x0, %al
callq 0x1030
movl $0x1, %edi
callq 0x1040
movl -0x34(%rbp), %eax
movl %eax, -0x54(%rbp)
movl -0x48(%rbp), %eax
movl %eax, -0x58(%rbp)
movl -0x54(%rbp), %eax
imull -0x58(%rbp), %eax
movslq %eax, %rdi
shlq $0x3, %rdi
callq 0x1070
movq %rax, -0x50(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x80(%rbp)
leaq -0x90(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1050
cvtsi2sdq -0x90(%rbp), %xmm0
cvtsi2sdq -0x88(%rbp), %xmm1
movsd 0xc73(%rip), %xmm2      # 0x2008
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, -0x80(%rbp)
xorps %xmm0, %xmm0
movsd %xmm0, -0x98(%rbp)
movl $0x0, -0x9c(%rbp)
movl -0x9c(%rbp), %eax
cmpl -0x34(%rbp), %eax
jge 0x14c9
movl $0x0, -0xa4(%rbp)
movl -0xa4(%rbp), %eax
cmpl -0x48(%rbp), %eax
jge 0x14b3
xorps %xmm0, %xmm0
movsd %xmm0, -0xb0(%rbp)
movl $0x0, -0xa0(%rbp)
movl -0xa0(%rbp), %eax
cmpl -0x44(%rbp), %eax
jge 0x147b
movq -0x30(%rbp), %rax
movl -0x9c(%rbp), %ecx
imull -0x38(%rbp), %ecx
addl -0xa0(%rbp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm0
movq -0x40(%rbp), %rax
movl -0xa0(%rbp), %ecx
imull -0x48(%rbp), %ecx
addl -0xa4(%rbp), %ecx
movslq %ecx, %rcx
movsd (%rax,%rcx,8), %xmm2
movsd -0xb0(%rbp), %xmm1
mulsd %xmm2, %xmm0
addsd %xmm1, %xmm0
movsd %xmm0, -0xb0(%rbp)
movsd 0xbb9(%rip), %xmm0      # 0x2010
addsd -0x98(%rbp), %xmm0
movsd %xmm0, -0x98(%rbp)
movl -0xa0(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa0(%rbp)
jmp 0x13f4
movsd -0xb0(%rbp), %xmm0
movq -0x50(%rbp), %rax
movl -0x58(%rbp), %ecx
imull -0x9c(%rbp), %ecx
addl -0xa4(%rbp), %ecx
movslq %ecx, %rcx
movsd %xmm0, (%rax,%rcx,8)
movl -0xa4(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa4(%rbp)
jmp 0x13d0
jmp 0x14b5
movl -0x9c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x9c(%rbp)
jmp 0x13b7
xorps %xmm0, %xmm0
movsd %xmm0, -0xb8(%rbp)
leaq -0xc8(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1050
cvtsi2sdq -0xc8(%rbp), %xmm0
cvtsi2sdq -0xc0(%rbp), %xmm1
movsd 0xb0a(%rip), %xmm2      # 0x2008
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, -0xb8(%rbp)
movq -0x70(%rbp), %rdi
movl -0x54(%rbp), %esi
movl -0x58(%rbp), %edx
movq -0x50(%rbp), %rcx
callq 0x17e0
movq -0x30(%rbp), %rdi
callq 0x1090
movq -0x40(%rbp), %rdi
callq 0x1090
movq -0x50(%rbp), %rdi
callq 0x1090
xorps %xmm0, %xmm0
movsd %xmm0, -0xd0(%rbp)
leaq -0xe0(%rbp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0x1050
cvtsi2sdq -0xe0(%rbp), %xmm0
cvtsi2sdq -0xd8(%rbp), %xmm1
movsd 0xa97(%rip), %xmm2      # 0x2008
divsd %xmm2, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, -0xd0(%rbp)
movsd -0xd0(%rbp), %xmm0
subsd -0xb8(%rbp), %xmm0
movsd -0x80(%rbp), %xmm1
subsd -0x18(%rbp), %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, -0xe8(%rbp)
movsd -0xb8(%rbp), %xmm0
subsd -0x80(%rbp), %xmm0
movsd %xmm0, -0xf0(%rbp)
movsd -0x98(%rbp), %xmm0
movsd 0xa3c(%rip), %xmm1      # 0x2008
divsd %xmm1, %xmm0
movsd %xmm0, -0xf8(%rbp)
movl -0x34(%rbp), %esi
movl -0x48(%rbp), %edx
leaq 0xad9(%rip), %rdi       # 0x20be
movb $0x0, %al
callq 0x1030
movsd -0xe8(%rbp), %xmm0
leaq 0xad1(%rip), %rdi       # 0x20cc
movb $0x1, %al
callq 0x1030
movsd -0xf0(%rbp), %xmm0
leaq 0xad4(%rip), %rdi       # 0x20e5
movb $0x1, %al
callq 0x1030
movsd -0xe8(%rbp), %xmm0
addsd -0xf0(%rbp), %xmm0
leaq 0xace(%rip), %rdi       # 0x20fd
movb $0x1, %al
callq 0x1030
movsd -0xf8(%rbp), %xmm0
divsd -0xf0(%rbp), %xmm0
movsd -0xf8(%rbp), %xmm1
movsd -0xe8(%rbp), %xmm2
addsd -0xf0(%rbp), %xmm2
divsd %xmm2, %xmm1
leaq 0xaa9(%rip), %rdi       # 0x2112
movb $0x2, %al
callq 0x1030
xorl %eax, %eax
addq $0x100, %rsp            # imm = 0x100
popq %rbp
retq
nopl (%rax,%rax)