// File: WeihuaZhu[P]hpc_prog2/mpi_jacobi.cpp
// Function: distribute_matrix(int, double*, double**, ompi_communicator_t*)
void distribute_matrix(const int n, double* input_matrix, double** local_matrix, MPI_Comm comm)
{
    // obtain the necessary parameters required in thie method
    int rank;
    MPI_Comm_rank(comm, &rank);
    int p;
    MPI_Comm_size(comm, &p);
    int q = sqrt(p);
    int dims[2];
    int coords[2];
    int periods[2];
    MPI_Cart_get(comm, 2, dims, periods, coords);
    int sourceRank;
    int sourceCoord[2] = {0, 0};
    MPI_Cart_rank(comm, sourceCoord, &sourceRank);

    //initialization of the dimention size in each processor
    int count_dim_0 = block_decompose_by_dim(n, comm, 0);
    int count_dim_1 = block_decompose_by_dim(n, comm, 1);

    //initialization of sendcounts and displs
    int *sendcounts = (int*) malloc(sizeof(int) * p);
    int *displs = (int*) malloc(sizeof(int) * p);
    displs[0] = 0;
    if (rank == sourceRank) {
        for (int i = 0; i < q; i++) {
            if (i != 0) {
                displs[i * q] = displs[i * q - 1] + sendcounts[i * q - 1] +
                    (block_decompose(n, q, i - 1) - 1) * n;
            }
            sendcounts[i * q] = (block_decompose(n, q, i) == 0) ? 0 : block_decompose(n, q, 0); //这里已经改了一些
            for (int j = 1; j < q; j++) {
                sendcounts[i * q + j] = (block_decompose(n, q, i) == 0) ? 0 : block_decompose(n, q, j);
                displs[i * q + j] = displs[i * q + j - 1] + sendcounts[i * q + j - 1];
            }
        }
    }

    //perform the matrix distribution for the first n/p lines in each processor
    *local_matrix = (double*) malloc(sizeof(double) * (count_dim_1 * count_dim_0));
    //In each iteration, send n/q lines of data in input matrix to the target place
    int rec_count = (count_dim_0 == 0) ? 0 : count_dim_1;
    for (int iter = 0; iter < n / q; iter++) {
        double *sendbuff = input_matrix + n * iter;
        double *rec_buff = *local_matrix + rec_count * iter;
        MPI_Scatterv(sendbuff, sendcounts, displs, MPI_DOUBLE, rec_buff, rec_count, MPI_DOUBLE, sourceRank, comm);
    }

    //deal with the leftover lines in the processors whose has the value: n % q != 0
    if (n % q != 0) {
        if (rank == 0) {
            for (int i = n % q; i < q; i++) {
                for (int j = 0; j < q; j++) {
                    sendcounts[i * q + j] = 0;
                    displs[i * q + j] = 0;
                }
            }
        }
        if (coords[0] >= n % q) rec_count = 0;
        int iter = n / q;
        double *sendbuff = input_matrix + n * iter;
        double *rec_buff = *local_matrix + rec_count * iter;
        MPI_Scatterv(sendbuff, sendcounts, displs, MPI_DOUBLE, rec_buff, rec_count, MPI_DOUBLE, sourceRank, comm);
    }

    // free the useless memory
    free(sendcounts);
    free(displs);
}

// Assembly:
subq $0xd8, %rsp
movl %edi, 0xd4(%rsp)
movq %rsi, 0xc8(%rsp)
movq %rdx, 0xc0(%rsp)
movq %rcx, 0xb8(%rsp)
movq 0xb8(%rsp), %rdi
leaq 0xb4(%rsp), %rsi
callq 0xf050
movq 0xb8(%rsp), %rdi
leaq 0xb0(%rsp), %rsi
callq 0xece0
movl 0xb0(%rsp), %edi
callq 0x119d0
cvttsd2si %xmm0, %eax
movl %eax, 0xac(%rsp)
movq 0xb8(%rsp), %rdi
leaq 0xa4(%rsp), %rdx
leaq 0x94(%rsp), %rcx
leaq 0x9c(%rsp), %r8
movl $0x2, %esi
callq 0xe8f0
leaq 0x88(%rsp), %rdi
xorl %esi, %esi
movl $0x8, %edx
callq 0xe510
movq 0xb8(%rsp), %rdi
leaq 0x88(%rsp), %rsi
leaq 0x90(%rsp), %rdx
callq 0xf4b0
movl 0xd4(%rsp), %edi
movq 0xb8(%rsp), %rsi
xorl %edx, %edx
callq 0x4e120
movl %eax, 0x84(%rsp)
movl 0xd4(%rsp), %edi
movq 0xb8(%rsp), %rsi
movl $0x1, %edx
callq 0x4e120
movl %eax, 0x80(%rsp)
movslq 0xb0(%rsp), %rdi
shlq $0x2, %rdi
callq 0xef20
movq %rax, 0x78(%rsp)
movslq 0xb0(%rsp), %rdi
shlq $0x2, %rdi
callq 0xef20
movq %rax, 0x70(%rsp)
movq 0x70(%rsp), %rax
movl $0x0, (%rax)
movl 0xb4(%rsp), %eax
cmpl 0x90(%rsp), %eax
jne 0x4d36e
movl $0x0, 0x6c(%rsp)
movl 0x6c(%rsp), %eax
cmpl 0xac(%rsp), %eax
jge 0x4d36c
cmpl $0x0, 0x6c(%rsp)
je 0x4d224
movq 0x70(%rsp), %rax
movl 0x6c(%rsp), %ecx
imull 0xac(%rsp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %eax
movq 0x78(%rsp), %rcx
movl 0x6c(%rsp), %edx
imull 0xac(%rsp), %edx
subl $0x1, %edx
movslq %edx, %rdx
addl (%rcx,%rdx,4), %eax
movl %eax, 0x2c(%rsp)
movl 0xd4(%rsp), %edi
movl 0xac(%rsp), %esi
movl 0x6c(%rsp), %edx
subl $0x1, %edx
callq 0x4e0e0
movl 0x2c(%rsp), %edx
subl $0x1, %eax
imull 0xd4(%rsp), %eax
addl %eax, %edx
movq 0x70(%rsp), %rax
movl 0x6c(%rsp), %ecx
imull 0xac(%rsp), %ecx
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
movl 0xd4(%rsp), %edi
movl 0xac(%rsp), %esi
movl 0x6c(%rsp), %edx
callq 0x4e0e0
cmpl $0x0, %eax
jne 0x4d248
xorl %eax, %eax
movl %eax, 0x28(%rsp)
jmp 0x4d261
movl 0xd4(%rsp), %edi
movl 0xac(%rsp), %esi
xorl %edx, %edx
callq 0x4e0e0
movl %eax, 0x28(%rsp)
movl 0x28(%rsp), %edx
movq 0x78(%rsp), %rax
movl 0x6c(%rsp), %ecx
imull 0xac(%rsp), %ecx
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
movl $0x1, 0x68(%rsp)
movl 0x68(%rsp), %eax
cmpl 0xac(%rsp), %eax
jge 0x4d35a
movl 0xd4(%rsp), %edi
movl 0xac(%rsp), %esi
movl 0x6c(%rsp), %edx
callq 0x4e0e0
cmpl $0x0, %eax
jne 0x4d2b9
xorl %eax, %eax
movl %eax, 0x24(%rsp)
jmp 0x4d2d4
movl 0xd4(%rsp), %edi
movl 0xac(%rsp), %esi
movl 0x68(%rsp), %edx
callq 0x4e0e0
movl %eax, 0x24(%rsp)
movl 0x24(%rsp), %edx
movq 0x78(%rsp), %rax
movl 0x6c(%rsp), %ecx
imull 0xac(%rsp), %ecx
addl 0x68(%rsp), %ecx
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
movq 0x70(%rsp), %rax
movl 0x6c(%rsp), %ecx
imull 0xac(%rsp), %ecx
addl 0x68(%rsp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
movl (%rax,%rcx,4), %edx
movq 0x78(%rsp), %rax
movl 0x6c(%rsp), %ecx
imull 0xac(%rsp), %ecx
addl 0x68(%rsp), %ecx
subl $0x1, %ecx
movslq %ecx, %rcx
addl (%rax,%rcx,4), %edx
movq 0x70(%rsp), %rax
movl 0x6c(%rsp), %ecx
imull 0xac(%rsp), %ecx
addl 0x68(%rsp), %ecx
movslq %ecx, %rcx
movl %edx, (%rax,%rcx,4)
movl 0x68(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x68(%rsp)
jmp 0x4d284
jmp 0x4d35c
movl 0x6c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x6c(%rsp)
jmp 0x4d192
jmp 0x4d36e
movl 0x80(%rsp), %eax
imull 0x84(%rsp), %eax
movslq %eax, %rdi
shlq $0x3, %rdi
callq 0xef20
movq %rax, %rcx
movq 0xc0(%rsp), %rax
movq %rcx, (%rax)
cmpl $0x0, 0x84(%rsp)
jne 0x4d3a9
xorl %eax, %eax
movl %eax, 0x20(%rsp)
jmp 0x4d3b4
movl 0x80(%rsp), %eax
movl %eax, 0x20(%rsp)
movl 0x20(%rsp), %eax
movl %eax, 0x64(%rsp)
movl $0x0, 0x60(%rsp)
movl 0x60(%rsp), %eax
movl %eax, 0x1c(%rsp)
movl 0xd4(%rsp), %eax
cltd
idivl 0xac(%rsp)
movl %eax, %ecx
movl 0x1c(%rsp), %eax
cmpl %ecx, %eax
jge 0x4d485
movq 0xc8(%rsp), %rax
movl 0xd4(%rsp), %ecx
imull 0x60(%rsp), %ecx
movslq %ecx, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x58(%rsp)
movq 0xc0(%rsp), %rax
movq (%rax), %rax
movl 0x64(%rsp), %ecx
imull 0x60(%rsp), %ecx
movslq %ecx, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x50(%rsp)
movq 0x58(%rsp), %rdi
movq 0x78(%rsp), %rsi
movq 0x70(%rsp), %rdx
movq 0x50(%rsp), %r8
movl 0x64(%rsp), %r9d
movl 0x90(%rsp), %r10d
movq 0xb8(%rsp), %rax
movq 0x1cb49(%rip), %r11     # 0x69fa8
movq %r11, %rcx
movq %r11, (%rsp)
movl %r10d, 0x8(%rsp)
movq %rax, 0x10(%rsp)
callq 0xe530
movl 0x60(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x60(%rsp)
jmp 0x4d3c4
movl 0xd4(%rsp), %eax
cltd
idivl 0xac(%rsp)
cmpl $0x0, %edx
je 0x4d605
cmpl $0x0, 0xb4(%rsp)
jne 0x4d53c
movl 0xd4(%rsp), %eax
cltd
idivl 0xac(%rsp)
movl %edx, 0x4c(%rsp)
movl 0x4c(%rsp), %eax
cmpl 0xac(%rsp), %eax
jge 0x4d53a
movl $0x0, 0x48(%rsp)
movl 0x48(%rsp), %eax
cmpl 0xac(%rsp), %eax
jge 0x4d52b
movq 0x78(%rsp), %rax
movl 0x4c(%rsp), %ecx
imull 0xac(%rsp), %ecx
addl 0x48(%rsp), %ecx
movslq %ecx, %rcx
movl $0x0, (%rax,%rcx,4)
movq 0x70(%rsp), %rax
movl 0x4c(%rsp), %ecx
imull 0xac(%rsp), %ecx
addl 0x48(%rsp), %ecx
movslq %ecx, %rcx
movl $0x0, (%rax,%rcx,4)
movl 0x48(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x48(%rsp)
jmp 0x4d4d3
jmp 0x4d52d
movl 0x4c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x4c(%rsp)
jmp 0x4d4be
jmp 0x4d53c
movl 0x9c(%rsp), %eax
movl %eax, 0x18(%rsp)
movl 0xd4(%rsp), %eax
cltd
idivl 0xac(%rsp)
movl 0x18(%rsp), %eax
cmpl %edx, %eax
jl 0x4d566
movl $0x0, 0x64(%rsp)
movl 0xd4(%rsp), %eax
cltd
idivl 0xac(%rsp)
movl %eax, 0x44(%rsp)
movq 0xc8(%rsp), %rax
movl 0xd4(%rsp), %ecx
imull 0x44(%rsp), %ecx
movslq %ecx, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x38(%rsp)
movq 0xc0(%rsp), %rax
movq (%rax), %rax
movl 0x64(%rsp), %ecx
imull 0x44(%rsp), %ecx
movslq %ecx, %rcx
shlq $0x3, %rcx
addq %rcx, %rax
movq %rax, 0x30(%rsp)
movq 0x38(%rsp), %rdi
movq 0x78(%rsp), %rsi
movq 0x70(%rsp), %rdx
movq 0x30(%rsp), %r8
movl 0x64(%rsp), %r9d
movl 0x90(%rsp), %r10d
movq 0xb8(%rsp), %rax
movq 0x1c9b9(%rip), %r11     # 0x69fa8
movq %r11, %rcx
movq %r11, (%rsp)
movl %r10d, 0x8(%rsp)
movq %rax, 0x10(%rsp)
callq 0xe530
movq 0x78(%rsp), %rdi
callq 0xed30
movq 0x70(%rsp), %rdi
callq 0xed30
addq $0xd8, %rsp
retq
nopw %cs:(%rax,%rax)