import numpy as np

from NFCT import NFCTplan


def main():
    rng = np.random.default_rng(1234)

    print("1d NFCT Test")

    N = np.array([50], dtype=np.int32)
    M = 100

    p = NFCTplan(N, M)

    print("Using:", p.lib_path)
    print("Number of Threads:", p.num_threads)

    A = np.ascontiguousarray(0.5 * rng.random(M), dtype=np.float64)
    p.x = A

    fhat = np.ascontiguousarray(rng.random(int(N[0])), dtype=np.float64)
    p.fhat = fhat

    f2 = p.trafo().copy()

    k = np.arange(0, int(N[0]))
    F = np.cos(2.0 * np.pi * np.outer(A, k))

    f1 = F @ fhat

    error_vector = f1 - f2
    E_2 = np.linalg.norm(error_vector) / np.linalg.norm(f1)
    E_infty = np.linalg.norm(error_vector, np.inf) / np.linalg.norm(fhat, 1)
    print("E_2 error:")
    print(E_2)
    print("E_infty error:")
    print(E_infty)

    if E_2 >= 1e-8 or E_infty >= 1e-8:
        raise RuntimeError("Errors are too large.")

    f2 = p.adjoint().copy()
    f1 = F.T @ p.f

    error_vector = f1 - f2
    E_2 = np.linalg.norm(error_vector) / np.linalg.norm(f1)
    E_infty = np.linalg.norm(error_vector, np.inf) / np.linalg.norm(fhat, 1)
    print("E_2 error:")
    print(E_2)
    print("E_infty error:")
    print(E_infty)

    if E_2 >= 1e-8 or E_infty >= 1e-8:
        raise RuntimeError("Errors are too large.")

    p.finalize()


if __name__ == "__main__":
    main()
