// File: /workspace/github_cpp_makefile_star2_O2/fanyazhi[P]Spline-Fitting/src/CRSmatrix.cpp
// Function: Jacobi(CRSmatrix, std::vector<double, std::allocator<double>>)
std::vector<double> Jacobi(CRSmatrix A, std::vector<double> b) {
    //first find the inverse of the diagonal matrix
    CRSmatrix Di = A;
    for (int i = 0; i < Di.getRowSize(); i++) {
        for (int j = 0; j < Di.getColSize(); j++) {
            //remove all elements other than the diagonal
            if (i != j) {
                Di.deleteValue(i, j);
            } else {
                //take the inverse of the diagonal
                for (int n = Di.rowPtr[i]; n < Di.rowPtr[i] + (Di.rowPtr[i + 1] - Di.rowPtr[i]); n++) {
                    if (Di.colInd[n] == j) {
                        Di.value[n] = 1 / Di.value[n];
                    }
                }
            }
        }
    }

    //find L+U
    CRSmatrix LU = A;
    for (int i = 0; i < LU.getRowSize(); i++) {
        for (int j = 0; j < LU.getColSize(); j++) {
            if (i == j) {
                LU.deleteValue(i, j);
            } else {
                //take the inverse of the diagonal
                for (int n = LU.rowPtr[i]; n < LU.rowPtr[i] + (LU.rowPtr[i + 1] - LU.rowPtr[i]); n++) {
                    if (LU.colInd[n] == j) {
                        LU.value[n] = -1.0 * LU.value[n];
                    }
                }
            }
        }
    }

    //take D^-1 * (L+U), store in DLU
    CRSmatrix DLU = LU;
    for (int i = 0; i < DLU.getRowSize(); i++) {
        for (int j = 0; j < DLU.getColSize(); j++) {
            for (int n = DLU.rowPtr[i]; n < DLU.rowPtr[i] + (DLU.rowPtr[i + 1] - DLU.rowPtr[i]); n++) {
                if (DLU.colInd[n] == j) {
                    DLU.value[n] = Di.value[i] * LU.retrieveElement(i, j);
                }
            }
        }
    }

    //find intercept D^-1 * b
    std::vector<double> cep(b.size());
    cep = Di.productAx(b);

    //initial guess is the same as the intercept
    std::vector<double> x = cep;

    //find vetor norm ||b-Ax|| of initial guess
    std::vector<double> normTemp(x.size());
    normTemp = A.productAx(x);
    for (unsigned int i = 0; i < b.size(); i++) {
        normTemp[i] = -1 * normTemp[i];
        normTemp[i] = b[i] + normTemp[i];
    }
    int count = 0;

    //start Jacobi iteration
    std::vector<double> xTemp(b.size());
    std::vector<double> prod(b.size());
    double threshold = 10E-7;
    while (vectorNorm(normTemp) > threshold) {
        count++;

        //x(k-1)
        for (unsigned int i = 0; i < b.size(); i++) {
            xTemp[i] = x[i];
        }

        //find product of D^-1(L+U)*x
        prod = DLU.productAx(xTemp);

        //add D^-1(L+U)*x to D^-1 * b, store in x
        for (unsigned int i = 0; i < x.size(); i++) {
            x[i] = prod[i] + cep[i];
        }

        //find new vetor norm ||x(k-1)-x||
        for (unsigned int i = 0; i < b.size(); i++) {
            normTemp[i] = -1.0 * x[i];
            normTemp[i] = xTemp[i] + normTemp[i];
        }
    }
    return x;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x208, %rsp            # imm = 0x208
movq %rdx, 0x8(%rsp)
movq %rdi, (%rsp)
leaq 0x120(%rsp), %r12
movq %r12, %rdi
movq %rsi, 0x20(%rsp)
callq 0x33fc
xorl %r13d, %r13d
movslq 0x120(%rsp), %rax
cmpq %rax, %r13
jge 0x2bc6
xorl %ebp, %ebp
cmpl 0x124(%rsp), %ebp
jge 0x2bc1
movl %ebp, %eax
cmpq %rax, %r13
jne 0x2bb0
movq 0x128(%rsp), %rax
movq 0x140(%rsp), %rdx
movslq (%rdx,%r13,4), %rcx
movslq 0x4(%rdx,%r13,4), %rdx
movq 0x158(%rsp), %rsi
cmpq %rdx, %rcx
jge 0x2bbd
cmpl %ebp, (%rsi,%rcx,4)
jne 0x2bab
movsd 0x246f(%rip), %xmm0     # 0x5010
divsd (%rax,%rcx,8), %xmm0
movsd %xmm0, (%rax,%rcx,8)
incq %rcx
jmp 0x2b8f
movq %r12, %rdi
movl %r13d, %esi
movl %ebp, %edx
callq 0x29da
incl %ebp
jmp 0x2b5e
incq %r13
jmp 0x2b4f
leaq 0xd0(%rsp), %rdi
movq 0x20(%rsp), %rsi
callq 0x33fc
xorl %r12d, %r12d
leaq 0xd0(%rsp), %r13
movslq 0xd0(%rsp), %rax
cmpq %rax, %r12
jge 0x2c58
xorl %ebp, %ebp
cmpl 0xd4(%rsp), %ebp
jge 0x2c53
movl %ebp, %eax
cmpq %rax, %r12
jne 0x2c13
movq %r13, %rdi
movl %r12d, %esi
movl %ebp, %edx
callq 0x29da
incl %ebp
jmp 0x2bf2
movq 0xd8(%rsp), %rax
movq 0xf0(%rsp), %rdx
movslq (%rdx,%r12,4), %rcx
movslq 0x4(%rdx,%r12,4), %rdx
movq 0x108(%rsp), %rsi
cmpq %rdx, %rcx
jge 0x2c0f
cmpl %ebp, (%rsi,%rcx,4)
jne 0x2c4e
movsd (%rax,%rcx,8), %xmm0
xorps 0x23d6(%rip), %xmm0     # 0x5020
movlps %xmm0, (%rax,%rcx,8)
incq %rcx
jmp 0x2c34
incq %r12
jmp 0x2be3
leaq 0x170(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0x33fc
movl 0x170(%rsp), %eax
movl 0x174(%rsp), %ecx
xorl %r12d, %r12d
testl %ecx, %ecx
cmovlel %r12d, %ecx
movl %ecx, 0x1c(%rsp)
testl %eax, %eax
cmovlel %r12d, %eax
movq %rax, 0x58(%rsp)
cmpq 0x58(%rsp), %r12
je 0x2d2a
movq 0x190(%rsp), %rax
movq %rax, 0x60(%rsp)
xorl %ebp, %ebp
cmpl 0x1c(%rsp), %ebp
je 0x2d22
movq 0x60(%rsp), %rax
movslq (%rax,%r12,4), %r15
movslq 0x4(%rax,%r12,4), %rbx
movq 0x178(%rsp), %rax
movq %rax, 0x68(%rsp)
movq 0x1a8(%rsp), %r13
movq 0x128(%rsp), %r14
cmpq %rbx, %r15
jge 0x2d1e
cmpl %ebp, (%r13,%r15,4)
jne 0x2d19
movsd (%r14,%r12,8), %xmm0
movsd %xmm0, 0x10(%rsp)
leaq 0xd0(%rsp), %rdi
movl %r12d, %esi
movl %ebp, %edx
callq 0x281a
mulsd 0x10(%rsp), %xmm0
movq 0x68(%rsp), %rax
movsd %xmm0, (%rax,%r15,8)
incq %r15
jmp 0x2cde
incl %ebp
jmp 0x2cad
incq %r12
jmp 0x2c93
movq 0x8(%rsp), %rbx
movq 0x8(%rbx), %rsi
subq (%rbx), %rsi
sarq $0x3, %rsi
leaq 0x88(%rsp), %rdi
leaq 0x40(%rsp), %rdx
callq 0x3336
leaq 0xb8(%rsp), %rdi
movq %rbx, %rsi
callq 0x3470
leaq 0x40(%rsp), %rdi
leaq 0x120(%rsp), %rsi
leaq 0xb8(%rsp), %rdx
callq 0x292c
leaq 0x88(%rsp), %r12
leaq 0x40(%rsp), %r13
movq %r12, %rdi
movq %r13, %rsi
callq 0x3b9a
movq %r13, %rdi
callq 0x3692
leaq 0xb8(%rsp), %rdi
callq 0x3692
movq (%rsp), %rbx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x3470
movq 0x8(%rbx), %rsi
subq (%rbx), %rsi
sarq $0x3, %rsi
leaq 0x40(%rsp), %rdi
leaq 0x28(%rsp), %rdx
callq 0x3336
leaq 0xa0(%rsp), %rdi
movq %rbx, %rsi
callq 0x3470
leaq 0x28(%rsp), %rdi
leaq 0xa0(%rsp), %rdx
movq 0x20(%rsp), %rsi
callq 0x292c
leaq 0x40(%rsp), %r15
leaq 0x28(%rsp), %r12
movq %r15, %rdi
movq %r12, %rsi
callq 0x3b9a
movq %r12, %rdi
callq 0x3692
leaq 0xa0(%rsp), %rdi
callq 0x3692
movq 0x8(%rsp), %rbx
movq (%rbx), %rax
movq 0x8(%rbx), %rsi
subq %rax, %rsi
sarq $0x3, %rsi
xorl %edx, %edx
movq (%r15), %rcx
movl %edx, %edx
cmpq %rdx, %rsi
jbe 0x2e64
movsd (%rcx,%rdx,8), %xmm0
movapd %xmm0, %xmm1
xorpd 0x21d3(%rip), %xmm1     # 0x5020
movlpd %xmm1, (%rcx,%rdx,8)
movsd (%rax,%rdx,8), %xmm1
subsd %xmm0, %xmm1
movsd %xmm1, (%rcx,%rdx,8)
incl %edx
jmp 0x2e35
leaq 0x28(%rsp), %rdi
leaq 0x70(%rsp), %rdx
callq 0x3336
movq 0x8(%rbx), %rsi
subq (%rbx), %rsi
sarq $0x3, %rsi
leaq 0x70(%rsp), %rdi
leaq 0x1d8(%rsp), %rdx
callq 0x3336
leaq 0x1f0(%rsp), %r15
leaq 0x40(%rsp), %rbx
leaq 0x1c0(%rsp), %r13
leaq 0x28(%rsp), %r14
leaq 0x1d8(%rsp), %rbp
leaq 0x70(%rsp), %r12
movq %r15, %rdi
movq %rbx, %rsi
callq 0x3470
movq %r15, %rdi
callq 0x2ade
movsd %xmm0, 0x10(%rsp)
movq %r15, %rdi
callq 0x3692
movsd 0x10(%rsp), %xmm0
ucomisd 0x2122(%rip), %xmm0     # 0x5008
jbe 0x2fe2
movq 0x8(%rsp), %rcx
movq 0x8(%rcx), %rax
subq (%rcx), %rax
sarq $0x3, %rax
movq (%rsp), %rcx
movq (%rcx), %rcx
xorl %esi, %esi
movq 0x28(%rsp), %rdx
movl %esi, %esi
cmpq %rsi, %rax
jbe 0x2f1f
movsd (%rcx,%rsi,8), %xmm0
movsd %xmm0, (%rdx,%rsi,8)
incl %esi
jmp 0x2f0a
movq %r13, %rdi
movq %r14, %rsi
callq 0x3470
movq %rbp, %rdi
leaq 0x170(%rsp), %rsi
movq %r13, %rdx
callq 0x292c
movq %r12, %rdi
movq %rbp, %rsi
callq 0x3b9a
movq %rbp, %rdi
callq 0x3692
movq %r13, %rdi
callq 0x3692
movq (%rsp), %rcx
movq (%rcx), %rax
movq 0x8(%rcx), %rcx
subq %rax, %rcx
sarq $0x3, %rcx
movq 0x70(%rsp), %rdx
xorl %edi, %edi
movq 0x88(%rsp), %rsi
movl %edi, %edi
cmpq %rdi, %rcx
jbe 0x2f93
movsd (%rdx,%rdi,8), %xmm0
addsd (%rsi,%rdi,8), %xmm0
movsd %xmm0, (%rax,%rdi,8)
incl %edi
jmp 0x2f79
movq 0x8(%rsp), %rdx
movq 0x8(%rdx), %rcx
subq (%rdx), %rcx
sarq $0x3, %rcx
movq 0x40(%rsp), %rdx
xorl %edi, %edi
movq 0x28(%rsp), %rsi
movl %edi, %edi
cmpq %rdi, %rcx
jbe 0x2eb7
movsd (%rax,%rdi,8), %xmm0
movapd %xmm0, %xmm1
xorpd 0x2055(%rip), %xmm1     # 0x5020
movlpd %xmm1, (%rdx,%rdi,8)
movsd (%rsi,%rdi,8), %xmm1
subsd %xmm0, %xmm1
movsd %xmm1, (%rdx,%rdi,8)
incl %edi
jmp 0x2faf
leaq 0x70(%rsp), %rdi
callq 0x3692
leaq 0x28(%rsp), %rdi
callq 0x3692
leaq 0x40(%rsp), %rdi
callq 0x3692
leaq 0x88(%rsp), %rdi
callq 0x3692
leaq 0x170(%rsp), %rdi
callq 0x34be
leaq 0xd0(%rsp), %rdi
callq 0x34be
leaq 0x120(%rsp), %rdi
callq 0x34be
movq (%rsp), %rax
addq $0x208, %rsp            # imm = 0x208
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %r14
jmp 0x30a6
jmp 0x305e
movq %rax, %r14
leaq 0xa0(%rsp), %rdi
jmp 0x30ab
movq %rax, %r14
jmp 0x30b0
movq %rax, %r14
jmp 0x30ba
jmp 0x3077
movq %rax, %r14
leaq 0xb8(%rsp), %rdi
jmp 0x30be
movq %rax, %r14
jmp 0x30c3
movq %rax, %r14
jmp 0x30d0
jmp 0x30df
jmp 0x30f1
movq %rax, %r14
leaq 0x1c0(%rsp), %rdi
callq 0x3692
jmp 0x309c
jmp 0x3099
movq %rax, %r14
leaq 0x70(%rsp), %rdi
callq 0x3692
leaq 0x28(%rsp), %rdi
callq 0x3692
leaq 0x40(%rsp), %rdi
callq 0x3692
movq (%rsp), %rdi
callq 0x3692
leaq 0x88(%rsp), %rdi
callq 0x3692
leaq 0x170(%rsp), %rdi
callq 0x34be
jmp 0x30e2
movq %rax, %r14
leaq 0xd0(%rsp), %rdi
callq 0x34be
jmp 0x30f4
movq %rax, %r14
leaq 0x120(%rsp), %rdi
callq 0x34be
movq %r14, %rdi
callq 0x2220
nop