import numpy as np


def table4_5():
    # inverse iteration

    # number of iterations
    K = 10

    # matrix
    n = 200
    A = np.zeros((n, n))
    a = 3
    for i in range(n):
        A[i, i] = a
    A[0, n - 1] = 1
    A[n - 1, 0] = 1

    # exact value
    evalue = 1 + a

    eig = np.zeros((2, K + 1))
    eig_err = np.zeros((2, K + 1))

    # try different shifts
    for icase in range(2):
        if icase == 0:
            mu = 4.8
        else:
            mu = 4.4
        B = A - mu * np.eye(n)
        evalueB = 1 / (1 + a - mu)
        y = np.random.rand(n)
        z = np.linalg.solve(B, y)
        v = np.dot(y, z) / np.dot(y, y)
        eig[icase, 0] = mu + 1 / v
        err = abs(evalue - eig[icase, 0])
        for k in range(1, K + 1):
            vv = v
            y = z / np.linalg.norm(z, 2)
            z = np.linalg.solve(B, y)
            v = np.dot(y, z)
            eig[icase, k] = mu + 1 / v
            eig_err[icase, k] = abs(eig[icase, k] - evalue)
            v0 = v

    print("\n k  \t   lambda_1 \t\t  Error   \t   lambda_1 \t\t  Error ")
    for kk in range(K + 1):
        print(
            f" {kk:d} \t {eig[0, kk]:15.12f}  \t {eig_err[0, kk]:5.2e}    \t "
            f"{eig[1, kk]:15.12f}  \t {eig_err[1, kk]:5.2e}  "
        )
        # print(f"{kk:d} \\,\\, & \\,\\, {eig[0,kk]:15.12f} \\,\\, & \\,\\, {eig_err[0,kk]:5.2e}  \\,\\, & \\,\\, {eig[1,kk]:15.12f} \\,\\, & \\,\\, {eig_err[1,kk]:5.2e} \\\\ \\hline ")


if __name__ == "__main__":
    table4_5()
