import numpy as np


def table4_9():
    # orthogonal iteration

    # number of iterations nd error tolerance
    K = 8
    tol = 1e-5

    # matrix
    n = 2
    A = np.zeros((n, n))
    A[0, 0] = 2
    A[0, 1] = 1
    A[1, 0] = 1
    A[1, 1] = 2

    # B=np.random.rand(n,n)
    B = np.zeros((n, n))
    B[0, 0] = -1
    B[0, 1] = 2
    B[1, 0] = 3
    B[1, 1] = -1

    # step 0
    Q, R = np.linalg.qr(B)
    eigens = np.zeros(n)
    for ic in range(n):
        eigens[ic] = np.dot(Q[:, ic], A @ Q[:, ic]) / np.dot(Q[:, ic], Q[:, ic])
    k = 0
    print("\n k  \t   lambda_1 \t   lambda_2 ")
    print(f" {k:d} \t {eigens[0]:12.8f} \t {eigens[1]:12.8f} ")
    # print(f"{k:d} & {eigens[0]:12.8f} & {eigens[1]:12.8f} ")
    eigens0 = eigens.copy()

    for k in range(1, K + 1):
        B = A @ Q
        Q, R = np.linalg.qr(B)
        for ic in range(n):
            eigens[ic] = np.dot(Q[:, ic], A @ Q[:, ic]) / np.dot(Q[:, ic], Q[:, ic])
        err = np.linalg.norm(eigens - eigens0, np.inf)
        eigens0 = eigens.copy()
        print(f" {k:d} \t {eigens[0]:12.8f} \t {eigens[1]:12.8f} ")
        # print(f"{k:d} & {eigens[0]:12.8f} & {eigens[1]:12.8f} ")
        if err < tol:
            break
    print()


if __name__ == "__main__":
    table4_9()
