// File: /workspace/github_cpp_makefile_star2_O1/btbujiangjun[P]abcdl/src/algebra/MatrixAlgebra.cpp
// Function: abcdl::algebra::Matrix<int>::inverse() const
Matrix<real> Matrix<T>::inverse() const{
    CHECK(_rows == _cols);
    //copy src mat
    Matrix<real> extend_mat = clone();
    //extend eye matrix
    extend_mat.extend(EyeMatrix<real>(_rows), Axis_type::COL);

    //adjust row
    size_t extend_mat_rows = extend_mat.rows();
    size_t extend_mat_cols = extend_mat.cols();
    for(size_t i = 0; i != extend_mat_rows; i++){
        if(extend_mat.get_data(i, i) == 0){
            size_t j;
            for(j = 0; j != extend_mat_rows; j++){
                if(extend_mat.get_data(j, i) != 0){
                    extend_mat.swap_row(i, j);
                    break;
                }
            }
            CHECK(j <= extend_mat_rows);//every element is zero in col i, cannot be inverse.
        }
    }

    //calc extend matrix
    for(size_t i = 0; i != extend_mat_rows; i++){
        //all element div the first element,to make diagonal elemnt is 1
        real diagonal_element = extend_mat.get_data(i, i);
        for(size_t j = 0; j < extend_mat_cols; j++){
            extend_mat.set_data(extend_mat.get_data(i, j)/diagonal_element, i, j);
        }

        //to make the element of other rows in col i is 0
        for(size_t m = 0; m != extend_mat_rows; m++){
            if(m == i){//skip itself
                continue;
            }
            real element = extend_mat.get_data(m, i);
            for(size_t n = 0; n != extend_mat_cols; n++){
                extend_mat.set_data(extend_mat.get_data(m, n) - extend_mat.get_data(i, n) * element, m, n);
            }
        }
    }

    //calc inverse matrix
    Matrix<real> result_mat(_rows, _cols);
    for(size_t i = 0; i != extend_mat_rows; i++){
        memcpy(&result_mat.data()[i * _cols], &extend_mat.data()[i * extend_mat_cols + _cols], sizeof(real) * _cols);
    }
    return result_mat;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x1d8, %rsp            # imm = 0x1D8
movq %rsi, %rbx
movq %rdi, %r12
movq (%rsi), %rax
cmpq 0x8(%rsi), %rax
jne 0x2a85b
leaq 0x50(%rsp), %r15
movq %r15, %rdi
movq %rbx, %rsi
callq 0x1957e
leaq 0x10(%rsp), %rdi
movq %r15, %rsi
callq 0x211ac
leaq 0x50(%rsp), %rdi
callq 0x186ec
movq (%rbx), %rsi
leaq 0x50(%rsp), %rdi
callq 0x1e4e8
movq %rbx, 0x40(%rsp)
leaq 0x10(%rsp), %rdi
leaq 0x50(%rsp), %rsi
movl $0x1, %edx
callq 0x1ab0c
leaq 0x50(%rsp), %rdi
callq 0x19c8e
movq 0x10(%rsp), %rbp
movq 0x18(%rsp), %rbx
testq %rbp, %rbp
je 0x2a7e1
movq %r12, 0x48(%rsp)
xorl %r15d, %r15d
leaq 0x10(%rsp), %r12
movq 0x18(%rsp), %rax
leaq 0x1(%rax), %r14
imulq %r15, %r14
imulq 0x10(%rsp), %rax
cmpq %rax, %r14
jae 0x2a3dd
movq 0x20(%rsp), %rax
movss (%rax,%r14,4), %xmm0
ucomiss 0x1215f(%rip), %xmm0    # 0x3c490
jne 0x2a3cf
jp 0x2a3cf
xorl %r13d, %r13d
movq 0x18(%rsp), %rax
movq %rax, %r14
imulq %r13, %r14
addq %r15, %r14
imulq 0x10(%rsp), %rax
cmpq %rax, %r14
jae 0x2a37a
movq 0x20(%rsp), %rax
movss (%rax,%r14,4), %xmm0
ucomiss 0x12124(%rip), %xmm0    # 0x3c490
jne 0x2a3b7
jp 0x2a3b7
incq %r13
cmpq %r13, %rbp
jne 0x2a340
jmp 0x2a3c7
leaq 0x50(%rsp), %rdi
leaq 0x120c7(%rip), %rsi     # 0x3c44d
movl $0x44, %edx
movl $0x3, %ecx
callq 0x3894e
movl $0x1f, %edx
leaq 0x50(%rsp), %rdi
leaq 0x1217a(%rip), %rsi     # 0x3c520
callq 0x93b0
leaq 0x50(%rsp), %rdi
callq 0x38b76
jmp 0x2a35a
movq %r12, %rdi
movq %r15, %rsi
movq %r13, %rdx
callq 0x1a482
jmp 0x2a3ca
movq %rbp, %r13
cmpq %rbp, %r13
ja 0x2a41c
incq %r15
cmpq %rbp, %r15
jne 0x2a303
jmp 0x2a45b
leaq 0x50(%rsp), %r13
movq %r13, %rdi
leaq 0x12061(%rip), %rsi     # 0x3c44d
movl $0x44, %edx
movl $0x3, %ecx
callq 0x3894e
movl $0x1f, %edx
movq %r13, %rdi
leaq 0x12116(%rip), %rsi     # 0x3c520
callq 0x93b0
movq %r13, %rdi
callq 0x38b76
jmp 0x2a31f
leaq 0x50(%rsp), %r14
movq %r14, %rdi
leaq 0x1336d(%rip), %rsi     # 0x3d798
movl $0x134, %edx            # imm = 0x134
movl $0x3, %ecx
callq 0x3894e
movl $0x22, %edx
movq %r14, %rdi
leaq 0x133bc(%rip), %rsi     # 0x3d805
callq 0x93b0
movq %r14, %rdi
callq 0x38b76
jmp 0x2a3cf
xorl %r15d, %r15d
leaq 0x50(%rsp), %rdx
movq 0x18(%rsp), %rax
leaq 0x1(%rax), %r14
imulq %r15, %r14
imulq 0x10(%rsp), %rax
cmpq %rax, %r14
jae 0x2a7a1
testq %rbx, %rbx
je 0x2a582
movq 0x20(%rsp), %rax
movss (%rax,%r14,4), %xmm0
movss %xmm0, 0xc(%rsp)
xorl %r14d, %r14d
movq 0x18(%rsp), %rax
movq %r15, %r12
imulq %rax, %r12
addq %r14, %r12
imulq 0x10(%rsp), %rax
cmpq %rax, %r12
jae 0x2a4f9
movq 0x18(%rsp), %rax
movq 0x20(%rsp), %rcx
movss (%rcx,%r12,4), %xmm0
movq %r15, %r13
imulq %rax, %r13
addq %r14, %r13
imulq 0x10(%rsp), %rax
cmpq %rax, %r13
jae 0x2a536
divss 0xc(%rsp), %xmm0
movq 0x20(%rsp), %rax
movss %xmm0, (%rax,%r13,4)
incq %r14
cmpq %r14, %rbx
jne 0x2a49c
jmp 0x2a582
movq %rdx, %r13
movq %rdx, %rdi
leaq 0x11f47(%rip), %rsi     # 0x3c44d
movl $0x44, %edx
movl $0x3, %ecx
callq 0x3894e
movl $0x1f, %edx
movq %r13, %rdi
leaq 0x11ffc(%rip), %rsi     # 0x3c520
callq 0x93b0
movq %r13, %rdi
callq 0x38b76
movq %r13, %rdx
jmp 0x2a4b6
movss %xmm0, 0x8(%rsp)
movq %rdx, %r12
movq %rdx, %rdi
leaq 0x11f04(%rip), %rsi     # 0x3c44d
movl $0x50, %edx
movl $0x3, %ecx
callq 0x3894e
movl $0x1f, %edx
movq %r12, %rdi
leaq 0x11fb9(%rip), %rsi     # 0x3c520
callq 0x93b0
movq %r12, %rdi
callq 0x38b76
movq %r12, %rdx
movss 0x8(%rsp), %xmm0
jmp 0x2a4db
xorl %r12d, %r12d
cmpq %r15, %r12
je 0x2a740
movq 0x18(%rsp), %rax
movq %rax, %r14
imulq %r12, %r14
addq %r15, %r14
imulq 0x10(%rsp), %rax
cmpq %rax, %r14
jae 0x2a74e
testq %rbx, %rbx
je 0x2a740
movq 0x20(%rsp), %rax
movss (%rax,%r14,4), %xmm0
movss %xmm0, 0x8(%rsp)
xorl %r14d, %r14d
movq 0x18(%rsp), %rax
movq %r12, %r13
imulq %rax, %r13
addq %r14, %r13
imulq 0x10(%rsp), %rax
cmpq %rax, %r13
jae 0x2a66b
movq 0x18(%rsp), %rax
movq 0x20(%rsp), %rcx
movss (%rcx,%r13,4), %xmm0
movss %xmm0, 0xc(%rsp)
movq %r15, %r13
imulq %rax, %r13
addq %r14, %r13
imulq 0x10(%rsp), %rax
cmpq %rax, %r13
jae 0x2a6ae
movq 0x18(%rsp), %rax
movq 0x20(%rsp), %rcx
movss (%rcx,%r13,4), %xmm1
mulss 0x8(%rsp), %xmm1
movq %r12, %r13
imulq %rax, %r13
addq %r14, %r13
imulq 0x10(%rsp), %rax
cmpq %rax, %r13
jae 0x2a6f1
movss 0xc(%rsp), %xmm0
subss %xmm1, %xmm0
movq 0x20(%rsp), %rax
movss %xmm0, (%rax,%r13,4)
incq %r14
cmpq %r14, %rbx
jne 0x2a5c9
jmp 0x2a740
movq %rdx, %rdi
leaq 0x11dd8(%rip), %rsi     # 0x3c44d
movl $0x44, %edx
movl $0x3, %ecx
callq 0x3894e
movl $0x1f, %edx
leaq 0x50(%rsp), %rdi
leaq 0x11e8b(%rip), %rsi     # 0x3c520
callq 0x93b0
leaq 0x50(%rsp), %rdi
callq 0x38b76
leaq 0x50(%rsp), %rdx
jmp 0x2a5e7
movq %rdx, %rdi
leaq 0x11d95(%rip), %rsi     # 0x3c44d
movl $0x44, %edx
movl $0x3, %ecx
callq 0x3894e
movl $0x1f, %edx
leaq 0x50(%rsp), %rdi
leaq 0x11e48(%rip), %rsi     # 0x3c520
callq 0x93b0
leaq 0x50(%rsp), %rdi
callq 0x38b76
leaq 0x50(%rsp), %rdx
jmp 0x2a616
movss %xmm1, 0x3c(%rsp)
movq %rdx, %rdi
leaq 0x11d4c(%rip), %rsi     # 0x3c44d
movl $0x50, %edx
movl $0x3, %ecx
callq 0x3894e
movl $0x1f, %edx
leaq 0x50(%rsp), %rdi
leaq 0x11dff(%rip), %rsi     # 0x3c520
callq 0x93b0
leaq 0x50(%rsp), %rdi
callq 0x38b76
leaq 0x50(%rsp), %rdx
movss 0x3c(%rsp), %xmm1
jmp 0x2a645
incq %r12
cmpq %rbp, %r12
jne 0x2a585
jmp 0x2a78e
movq %rdx, %r13
movq %rdx, %rdi
leaq 0x11cf2(%rip), %rsi     # 0x3c44d
movl $0x44, %edx
movl $0x3, %ecx
callq 0x3894e
movl $0x1f, %edx
movq %r13, %rdi
leaq 0x11da7(%rip), %rsi     # 0x3c520
callq 0x93b0
movq %r13, %rdi
callq 0x38b76
movq %r13, %rdx
jmp 0x2a5ac
incq %r15
cmpq %rbp, %r15
movq 0x48(%rsp), %r12
jne 0x2a463
jmp 0x2a7e1
movq %rdx, %r12
movq %rdx, %rdi
leaq 0x11c9f(%rip), %rsi     # 0x3c44d
movl $0x44, %edx
movl $0x3, %ecx
callq 0x3894e
movl $0x1f, %edx
movq %r12, %rdi
leaq 0x11d54(%rip), %rsi     # 0x3c520
callq 0x93b0
movq %r12, %rdi
callq 0x38b76
movq %r12, %rdx
jmp 0x2a47f
movq 0x40(%rsp), %rax
movq (%rax), %rsi
movq 0x8(%rax), %rdx
movq %r12, %rdi
callq 0x19a56
testq %rbp, %rbp
movq 0x40(%rsp), %r13
je 0x2a83c
shlq $0x2, %rbx
xorl %r14d, %r14d
xorl %r15d, %r15d
movq 0x8(%r13), %rdx
movq %rdx, %rdi
imulq %r15, %rdi
shlq $0x2, %rdi
addq 0x10(%r12), %rdi
shlq $0x2, %rdx
movq 0x20(%rsp), %rsi
addq %rdx, %rsi
addq %r14, %rsi
callq 0x92b0
incq %r15
addq %rbx, %r14
cmpq %r15, %rbp
jne 0x2a809
leaq 0x10(%rsp), %rdi
callq 0x19c8e
movq %r12, %rax
addq $0x1d8, %rsp            # imm = 0x1D8
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x12f36(%rip), %rsi     # 0x3d798
leaq 0x50(%rsp), %r15
movq %r15, %rdi
movl $0x122, %edx            # imm = 0x122
movl $0x3, %ecx
callq 0x3894e
leaq 0x12f68(%rip), %rsi     # 0x3d7e8
movl $0x1c, %edx
movq %r15, %rdi
callq 0x93b0
leaq 0x50(%rsp), %rdi
callq 0x38b76
jmp 0x2a28c
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x38b76
jmp 0x2a909
jmp 0x2a8eb
jmp 0x2a8fc
jmp 0x2a8eb
jmp 0x2a8fc
jmp 0x2a8eb
jmp 0x2a8fc
jmp 0x2a8eb
jmp 0x2a8fc
jmp 0x2a8eb
jmp 0x2a8fc
jmp 0x2a8eb
jmp 0x2a8eb
jmp 0x2a8fc
jmp 0x2a8fc
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x19c8e
jmp 0x2a8ff
jmp 0x2a8fc
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x186ec
jmp 0x2a909
jmp 0x2a8eb
jmp 0x2a8eb
movq %rax, %rbx
leaq 0x50(%rsp), %rdi
callq 0x38b76
jmp 0x2a8ff
jmp 0x2a8fc
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x19c8e
movq %rbx, %rdi
callq 0x95d0
nop