// File: Krymancer[P]Matrix-cpp/src/Matrix.cpp
// Function: Matrix::powerIter(unsigned int, double)
tuple<Matrix, double, int> Matrix::powerIter(unsigned rowNum, double tolerance) {
    // Picks a classic X vector
    Matrix X(rowNum, 1, 1.0);
    // Initiates X vector with values 1,2,3,4
    for (unsigned i = 1; i <= rowNum; i++) {
        X(i - 1, 0) = i;
    }
    int errorCode = 0;
    double difference = 1.0;  // Initiall value greater than tolerance
    unsigned j = 0;
    unsigned location;
    // Defined to find the value between last two eigen values
    vector<double> eigen;
    double eigenvalue = 0.0;
    eigen.push_back(0.0);

    while (abs(difference) > tolerance) {  // breaks out when reached tolerance
        j++;
        // Normalize X vector with infinite norm
        for (int i = 0; i < rowNum; ++i) {
            eigenvalue = X(0, 0);
            if (abs(X(i, 0)) >= abs(eigenvalue)) {
                // Take the value of the infinite norm as your eigenvalue
                eigenvalue = X(i, 0);
                location = i;
            }
        }
        if (j >= 5e5) {
            std::cout << "Oops, that was a nasty complex number wasn't it?\n";
            std::cout << "ERROR! Returning code black, code black!";
            errorCode = -1;
            return std::make_tuple(X, 0.0, errorCode);
        }
        eigen.push_back(eigenvalue);
        difference = eigen[j] - eigen[j - 1];
        // Normalize X vector with its infinite norm
        X = X / eigenvalue;

        // Multiply The matrix with X vector
        X = (*this) * X;
    }

    // Take the X vector and what you've found is an eigenvector!
    X = X / eigenvalue;
    return std::make_tuple(X, eigenvalue, errorCode);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x180, %rsp            # imm = 0x180
movq %rdi, -0x138(%rbp)
movq %rdi, %rax
movq %rax, -0x130(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movsd %xmm0, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq %rax, -0x128(%rbp)
movl -0x14(%rbp), %esi
leaq -0x40(%rbp), %rdi
movl $0x1, %edx
movsd 0x8c9d(%rip), %xmm0     # 0xd008
callq 0x2550
movl $0x1, -0x44(%rbp)
movl -0x44(%rbp), %eax
cmpl -0x14(%rbp), %eax
ja 0x43c7
movl -0x44(%rbp), %eax
cvtsi2sd %rax, %xmm0
movsd %xmm0, -0x140(%rbp)
movl -0x44(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x48(%rbp)
movl $0x0, -0x4c(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0x48(%rbp), %rsi
leaq -0x4c(%rbp), %rdx
callq 0x2ef0
movsd -0x140(%rbp), %xmm0
movsd %xmm0, (%rax)
movl -0x44(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x44(%rbp)
jmp 0x4377
movl $0x0, -0x50(%rbp)
movabsq $0x3ff0000000000000, %rax # imm = 0x3FF0000000000000
movq %rax, -0x58(%rbp)
movl $0x0, -0x5c(%rbp)
leaq -0x78(%rbp), %rdi
movq %rdi, -0x148(%rbp)
callq 0x5480
movq -0x148(%rbp), %rdi
movq $0x0, -0x80(%rbp)
movq $0x0, -0x88(%rbp)
leaq -0x88(%rbp), %rsi
callq 0x55b0
jmp 0x441b
jmp 0x441d
movsd -0x58(%rbp), %xmm0
callq 0x55e0
movsd %xmm0, -0x150(%rbp)
jmp 0x4431
movsd -0x150(%rbp), %xmm0
ucomisd -0x20(%rbp), %xmm0
jbe 0x4709
movl -0x5c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x5c(%rbp)
movl $0x0, -0x98(%rbp)
movl -0x98(%rbp), %eax
cmpl -0x14(%rbp), %eax
jae 0x457c
movl $0x0, -0x9c(%rbp)
movl $0x0, -0xa0(%rbp)
leaq -0x40(%rbp), %rdi
movq %rdi, -0x160(%rbp)
leaq -0x9c(%rbp), %rsi
leaq -0xa0(%rbp), %rdx
callq 0x2ef0
movq -0x160(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x80(%rbp)
movl -0x98(%rbp), %eax
movl %eax, -0xa4(%rbp)
movl $0x0, -0xa8(%rbp)
leaq -0xa4(%rbp), %rsi
leaq -0xa8(%rbp), %rdx
callq 0x2ef0
movsd (%rax), %xmm0
callq 0x55e0
movsd %xmm0, -0x158(%rbp)
jmp 0x44e4
movsd -0x80(%rbp), %xmm0
callq 0x55e0
movsd %xmm0, -0x168(%rbp)
jmp 0x44f8
movsd -0x158(%rbp), %xmm0
movsd -0x168(%rbp), %xmm1
ucomisd %xmm1, %xmm0
jb 0x4566
movl -0x98(%rbp), %eax
movl %eax, -0xac(%rbp)
movl $0x0, -0xb0(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0xac(%rbp), %rsi
leaq -0xb0(%rbp), %rdx
callq 0x2ef0
movsd (%rax), %xmm0
movsd %xmm0, -0x80(%rbp)
movl -0x98(%rbp), %eax
movl %eax, -0x60(%rbp)
jmp 0x4566
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
jmp 0x47a6
jmp 0x4568
movl -0x98(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x98(%rbp)
jmp 0x4457
movl -0x5c(%rbp), %eax
cvtsi2sd %rax, %xmm0
movsd 0x8a84(%rip), %xmm1     # 0xd010
ucomisd %xmm1, %xmm0
jb 0x45fa
movq 0xea3f(%rip), %rdi      # 0x12fd8
leaq 0x8b2d(%rip), %rsi      # 0xd0cd
callq 0x21d0
jmp 0x45a7
movq 0xea2a(%rip), %rdi      # 0x12fd8
leaq 0x8b4a(%rip), %rsi      # 0xd0ff
callq 0x21d0
jmp 0x45bc
movq -0x138(%rbp), %rdi
movl $0xffffffff, -0x50(%rbp) # imm = 0xFFFFFFFF
movq $0x0, -0xb8(%rbp)
leaq -0x40(%rbp), %rsi
leaq -0xb8(%rbp), %rdx
leaq -0x50(%rbp), %rcx
callq 0x5600
jmp 0x45eb
movl $0x1, -0xbc(%rbp)
jmp 0x4784
leaq -0x78(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x54a0
jmp 0x4609
movl -0x5c(%rbp), %eax
movl %eax, %esi
leaq -0x78(%rbp), %rdi
movq %rdi, -0x178(%rbp)
callq 0x5190
movq -0x178(%rbp), %rdi
movsd (%rax), %xmm0
movsd %xmm0, -0x170(%rbp)
movl -0x5c(%rbp), %eax
decl %eax
movl %eax, %esi
callq 0x5190
movsd -0x170(%rbp), %xmm0
movsd (%rax), %xmm1
subsd %xmm1, %xmm0
movsd %xmm0, -0x58(%rbp)
movsd -0x80(%rbp), %xmm0
leaq -0xe0(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x3b20
jmp 0x4669
leaq -0x40(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
callq 0x5440
jmp 0x467b
leaq -0xe0(%rbp), %rdi
callq 0x5420
movq -0x128(%rbp), %rsi
leaq -0x100(%rbp), %rdi
leaq -0x40(%rbp), %rdx
callq 0x3100
jmp 0x46a0
leaq -0x40(%rbp), %rdi
leaq -0x100(%rbp), %rsi
callq 0x5440
jmp 0x46b2
leaq -0x100(%rbp), %rdi
callq 0x5420
jmp 0x441d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0xe0(%rbp), %rdi
callq 0x5420
jmp 0x47a6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x100(%rbp), %rdi
callq 0x5420
jmp 0x47a6
movsd -0x80(%rbp), %xmm0
leaq -0x120(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x3b20
jmp 0x4720
leaq -0x40(%rbp), %rdi
leaq -0x120(%rbp), %rsi
callq 0x5440
jmp 0x4732
leaq -0x120(%rbp), %rdi
callq 0x5420
movq -0x138(%rbp), %rdi
leaq -0x40(%rbp), %rsi
leaq -0x80(%rbp), %rdx
leaq -0x50(%rbp), %rcx
callq 0x5640
jmp 0x4758
movl $0x1, -0xbc(%rbp)
jmp 0x4784
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x90(%rbp)
movl %eax, -0x94(%rbp)
leaq -0x120(%rbp), %rdi
callq 0x5420
jmp 0x47a6
leaq -0x78(%rbp), %rdi
callq 0x5510
leaq -0x40(%rbp), %rdi
callq 0x5420
movq -0x130(%rbp), %rax
addq $0x180, %rsp            # imm = 0x180
popq %rbp
retq
leaq -0x78(%rbp), %rdi
callq 0x5510
leaq -0x40(%rbp), %rdi
callq 0x5420
movq -0x90(%rbp), %rdi
callq 0x2350
nopw %cs:(%rax,%rax)