// File: WeihuaZhu[P]hpc_prog2/mpi_tests.cpp
// Function: MpiTest_MatrixVectorMult1_Test::TestBody()
TEST(MpiTest, MatrixVectorMult1)
{
    // simple 4 by 4 input matrix
    double A[4*4] = {10., -1., 2., 0.,
                           -1., 11., -1., 3.,
                           2., -1., 10., -1.,
                           0.0, 3., -1., 8.};
    double x[4] =  {6., 25., -11., 15.};
    double y[4];
    double expected_y[4] = {13.,  325., -138.,  206.};
    int n = 4;

    // get grid communicator
    MPI_Comm grid_comm;
    get_grid_comm(&grid_comm);

    // testing sequential matrix multiplication
    mpi_matrix_vector_mult(n, A, x, y, grid_comm);

    // checking if all values are correct (up to some error value)
    for (int i = 0; i < n; ++i)
    {
        EXPECT_NEAR(expected_y[i], y[i], 1e-10) << " element y[" << i << "] is wrong";
    }
}

// Assembly:
subq $0x168, %rsp            # imm = 0x168
movq %rdi, 0x160(%rsp)
leaq 0xe0(%rsp), %rdi
leaq 0x3e9f2(%rip), %rsi     # 0x4f1b0
movl $0x80, %edx
callq 0xe870
movq 0x3eb41(%rip), %rax     # 0x4f310
movq %rax, 0xc0(%rsp)
movq 0x3eb3a(%rip), %rax     # 0x4f318
movq %rax, 0xc8(%rsp)
movq 0x3eb33(%rip), %rax     # 0x4f320
movq %rax, 0xd0(%rsp)
movq 0x3eb2c(%rip), %rax     # 0x4f328
movq %rax, 0xd8(%rsp)
movq 0x3eb25(%rip), %rax     # 0x4f330
movq %rax, 0x80(%rsp)
movq 0x3eb1e(%rip), %rax     # 0x4f338
movq %rax, 0x88(%rsp)
movq 0x3eb17(%rip), %rax     # 0x4f340
movq %rax, 0x90(%rsp)
movq 0x3eb10(%rip), %rax     # 0x4f348
movq %rax, 0x98(%rsp)
movl $0x4, 0x7c(%rsp)
leaq 0x70(%rsp), %rdi
callq 0x105a0
movl 0x7c(%rsp), %edi
leaq 0xe0(%rsp), %rsi
leaq 0xc0(%rsp), %rdx
leaq 0xa0(%rsp), %rcx
movq 0x70(%rsp), %r8
callq 0x4df20
movl $0x0, 0x6c(%rsp)
movl 0x6c(%rsp), %eax
cmpl 0x7c(%rsp), %eax
jge 0x10a09
movslq 0x6c(%rsp), %rax
movsd 0x80(%rsp,%rax,8), %xmm0
movsd 0xa0(%rsp,%rax,8), %xmm1
leaq 0x3e81f(%rip), %rsi     # 0x4f0cb
leaq 0x3e821(%rip), %rdx     # 0x4f0d4
leaq 0x3e81f(%rip), %rcx     # 0x4f0d9
leaq 0x58(%rsp), %rdi
movq %rdi, 0x28(%rsp)
movsd 0x3e75c(%rip), %xmm2    # 0x4f028
callq 0x1c2f0
movq 0x28(%rsp), %rdi
callq 0x11a40
movb %al, 0x37(%rsp)
jmp 0x108e1
movb 0x37(%rsp), %al
testb $0x1, %al
jne 0x108eb
jmp 0x10903
jmp 0x109e3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x50(%rsp)
movl %eax, 0x4c(%rsp)
jmp 0x109fd
leaq 0x40(%rsp), %rdi
callq 0x1b7b0
jmp 0x1090f
leaq 0x3e7c9(%rip), %rsi     # 0x4f0df
leaq 0x40(%rsp), %rdi
callq 0x11b20
movq %rax, 0x20(%rsp)
jmp 0x10927
movq 0x20(%rsp), %rdi
leaq 0x6c(%rsp), %rsi
callq 0x11b60
movq %rax, 0x18(%rsp)
jmp 0x1093d
movq 0x18(%rsp), %rdi
leaq 0x3e7a2(%rip), %rsi     # 0x4f0eb
callq 0x11ba0
movq %rax, 0x10(%rsp)
jmp 0x10955
leaq 0x58(%rsp), %rdi
callq 0x11a90
movq %rax, 0x8(%rsp)
jmp 0x10966
movq 0x8(%rsp), %r8
leaq 0x3e731(%rip), %rdx     # 0x4f0a3
leaq 0x38(%rsp), %rdi
movl $0x1, %esi
movl $0x46, %ecx
callq 0x188e0
jmp 0x10988
movq 0x10(%rsp), %rsi
leaq 0x38(%rsp), %rdi
callq 0x189b0
jmp 0x10999
leaq 0x38(%rsp), %rdi
callq 0x18970
leaq 0x40(%rsp), %rdi
callq 0x11aa0
jmp 0x109e3
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x50(%rsp)
movl %eax, 0x4c(%rsp)
jmp 0x109d7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x50(%rsp)
movl %eax, 0x4c(%rsp)
leaq 0x38(%rsp), %rdi
callq 0x18970
leaq 0x40(%rsp), %rdi
callq 0x11aa0
jmp 0x109fd
leaq 0x58(%rsp), %rdi
callq 0x11ab0
movl 0x6c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x6c(%rsp)
jmp 0x10880
leaq 0x58(%rsp), %rdi
callq 0x11ab0
jmp 0x10a11
addq $0x168, %rsp            # imm = 0x168
retq
movq 0x50(%rsp), %rdi
callq 0xf440
nopl (%rax,%rax)