import numpy as np
import matplotlib.pyplot as plt
from cycler import cycler

from plot_helpers import CO, bold_ticks


def fig6_6():
    # this includes Fig 6.6 and Table 6.2

    # Integrate f(x) over [a, b] using Trap rule
    #
    # Inputs:
    #       a = left endpoint of interval
    #       b = right endpoint of interval
    #       n = number of subintervals

    a = 0
    b = 1
    exact = (np.exp(3) - 1) / 3

    # interv = number of subinternals
    interv = np.array([1000, 2000, 4000, 8000, 16000, 32000])
    nk = len(interv)
    T = np.zeros(nk)
    err = np.zeros(nk)
    for k in range(nk):
        n = int(interv[k])
        T[k] = trap(a, b, n)
        err[k] = abs(exact - T[k])

    # table 6.2
    print("\n RIE = relative iterative error \n")
    print(" k \t  n  \t\t I_M \t \t Error \t\t RIE")
    print(f" {1:d} \t {interv[0]:d}\t {T[0]:19.15f} \t {err[0]:5.1e}")
    # print('\\, %i \\, & ...')
    for k in range(1, nk):
        rie = abs((T[k] - T[k - 1]) / T[k])
        print(
            f" {k + 1:d} \t {interv[k]:d} \t {T[k]:19.15f} "
            f"\t {err[k]:5.1e}  \t {rie:5.1e}"
        )
        # print('\\, %i \\, & ...')
    print()

    ### fig 6.6
    plt.close("all")
    # get(gcf)
    fig, ax = plt.subplots(figsize=(8.8, 3.3))
    fig.subplots_adjust(left=0.08, right=0.98, bottom=0.22, top=0.98)
    ax.set_prop_cycle(cycler(color=CO))

    n = 3
    xd = np.linspace(a, b, n + 1)
    h = xd[1] - xd[0]
    for in_ in range(n):
        ax.plot(
            [xd[in_], xd[in_ + 1]],
            [f(xd[in_]), f(xd[in_ + 1])],
            "--r",
            linewidth=2,
        )
        ax.plot(
            [xd[in_], xd[in_]],
            [0, f(xd[in_])],
            "--r",
            linewidth=2,
        )
    ax.plot([0.999 * b, 0.999 * b], [0, f(b)], "--r", linewidth=2)

    nx = 100
    x = np.linspace(a, b, nx)
    y = np.zeros(nx)
    for ix in range(nx):
        y[ix] = f(x[ix])
    ax.plot(x, y, linewidth=1.6)
    # ax.grid(True)
    ax.set_xlabel("x-axis", fontsize=14)
    ax.set_ylabel("y-axis", fontsize=14)
    ax.set_xlim(0, 1)
    ax.set_ylim(0, 20)
    ax.set_xticks([0, 1 / 3, 2 / 3, 1])
    ax.set_xticklabels(["0", "1/3", "2/3", "1"])
    # ax.yaxis.grid(False, which="minor")
    bold_ticks(ax, 14)
    for spine in ax.spines.values():
        spine.set_visible(True)
    plt.show()

    # plt.savefig('/Users/mark/Desktop/expT.eps')


def f(x):
    y = np.exp(3 * x)
    return y


### composite trap: n = number of subintervals
def trap(a, b, n):
    xd = np.linspace(a, b, n + 1)
    h = xd[1] - xd[0]
    s = 0.5 * f(xd[0])
    for j in range(1, n):
        s = s + f(xd[j])
    s = h * (s + 0.5 * f(xd[n]))
    return s


if __name__ == "__main__":
    fig6_6()
