// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2026 Rasmus Munk Larsen <rmlarsen@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
// SPDX-License-Identifier: MPL-2.0

// Tests for GpuSelfAdjointEigenSolver: GPU symmetric/Hermitian eigenvalue
// decomposition via cuSOLVER.

#define EIGEN_USE_GPU
#include "main.h"
#include <Eigen/Eigenvalues>
#include <contrib/Eigen/GPU>

#include "./gpu_test_helpers.h"

using namespace Eigen;

// ---- Reconstruction: V * diag(W) * V^H ≈ A ---------------------------------

template <typename Scalar>
void test_eigen_reconstruction(Index n) {
  using Mat = Matrix<Scalar, Dynamic, Dynamic>;
  using RealScalar = typename NumTraits<Scalar>::Real;

  // Build a symmetric/Hermitian matrix.
  Mat R = Mat::Random(n, n);
  Mat A = R + R.adjoint();

  gpu::SelfAdjointEigenSolver<Scalar> es(A);
  VERIFY_IS_EQUAL(es.info(), Success);

  auto W = es.eigenvalues();
  Mat V = es.eigenvectors();

  VERIFY_IS_EQUAL(W.size(), n);
  VERIFY_IS_EQUAL(V.rows(), n);
  VERIFY_IS_EQUAL(V.cols(), n);

  // Reconstruct: A_hat = V * diag(W) * V^H.
  Mat A_hat = V * W.asDiagonal() * V.adjoint();
  RealScalar tol = RealScalar(8) * static_cast<RealScalar>(n) * NumTraits<Scalar>::epsilon() * A.norm();
  VERIFY((A_hat - A).norm() < tol);

  // Orthogonality: V^H * V ≈ I.
  Mat VhV = V.adjoint() * V;
  Mat eye = Mat::Identity(n, n);
  VERIFY((VhV - eye).norm() < tol);
}

// ---- Eigenvalues match CPU SelfAdjointEigenSolver ---------------------------

template <typename Scalar>
void test_eigen_values(Index n) {
  using Mat = Matrix<Scalar, Dynamic, Dynamic>;
  using RealScalar = typename NumTraits<Scalar>::Real;

  Mat R = Mat::Random(n, n);
  Mat A = R + R.adjoint();

  gpu::SelfAdjointEigenSolver<Scalar> gpu_es(A);
  VERIFY_IS_EQUAL(gpu_es.info(), Success);
  auto W_gpu = gpu_es.eigenvalues();

  SelfAdjointEigenSolver<Mat> cpu_es(A);
  auto W_cpu = cpu_es.eigenvalues();

  RealScalar tol =
      RealScalar(2) * static_cast<RealScalar>(n) * NumTraits<Scalar>::epsilon() * W_cpu.cwiseAbs().maxCoeff();
  VERIFY((W_gpu - W_cpu).norm() < tol);
}

// ---- Eigenvalues-only mode --------------------------------------------------

template <typename Scalar>
void test_eigen_values_only(Index n) {
  using Mat = Matrix<Scalar, Dynamic, Dynamic>;
  using RealScalar = typename NumTraits<Scalar>::Real;

  Mat R = Mat::Random(n, n);
  Mat A = R + R.adjoint();

  gpu::SelfAdjointEigenSolver<Scalar> gpu_es(A, EigenvaluesOnly);
  VERIFY_IS_EQUAL(gpu_es.info(), Success);
  auto W_gpu = gpu_es.eigenvalues();

  SelfAdjointEigenSolver<Mat> cpu_es(A, EigenvaluesOnly);
  auto W_cpu = cpu_es.eigenvalues();

  RealScalar tol =
      RealScalar(2) * static_cast<RealScalar>(n) * NumTraits<Scalar>::epsilon() * W_cpu.cwiseAbs().maxCoeff();
  VERIFY((W_gpu - W_cpu).norm() < tol);
}

// ---- DeviceMatrix input path ------------------------------------------------

template <typename Scalar>
void test_eigen_device_matrix(Index n) {
  using Mat = Matrix<Scalar, Dynamic, Dynamic>;
  using RealScalar = typename NumTraits<Scalar>::Real;

  Mat R = Mat::Random(n, n);
  Mat A = R + R.adjoint();

  auto d_A = gpu::DeviceMatrix<Scalar>::fromHost(A);
  gpu::SelfAdjointEigenSolver<Scalar> es;
  es.compute(d_A);
  VERIFY_IS_EQUAL(es.info(), Success);

  auto W_gpu = es.eigenvalues();
  Mat V = es.eigenvectors();

  // Verify reconstruction.
  Mat A_hat = V * W_gpu.asDiagonal() * V.adjoint();
  RealScalar tol = RealScalar(8) * static_cast<RealScalar>(n) * NumTraits<Scalar>::epsilon() * A.norm();
  VERIFY((A_hat - A).norm() < tol);

  // Context-bound rvalue constructor adopts d_A instead of copying it.
  gpu::Context ctx;
  auto d_A_ctx = gpu::DeviceMatrix<Scalar>::fromHost(A, ctx.stream());
  gpu::SelfAdjointEigenSolver<Scalar> es_ctx(ctx, std::move(d_A_ctx));
  VERIFY(d_A_ctx.empty());
  VERIFY_IS_EQUAL(es_ctx.info(), Success);
  VERIFY(es_ctx.stream() == ctx.stream());
  Mat V_ctx = es_ctx.eigenvectors();
  VERIFY((V_ctx * es_ctx.eigenvalues().asDiagonal() * V_ctx.adjoint() - A).norm() < tol);
}

// ---- Recompute (reuse solver object) ----------------------------------------

template <typename Scalar>
void test_eigen_recompute(Index n) {
  using Mat = Matrix<Scalar, Dynamic, Dynamic>;
  using RealScalar = typename NumTraits<Scalar>::Real;

  gpu::SelfAdjointEigenSolver<Scalar> es;

  for (int trial = 0; trial < 3; ++trial) {
    Mat R = Mat::Random(n, n);
    Mat A = R + R.adjoint();
    es.compute(A);
    VERIFY_IS_EQUAL(es.info(), Success);

    auto W = es.eigenvalues();
    Mat V = es.eigenvectors();
    Mat A_hat = V * W.asDiagonal() * V.adjoint();
    RealScalar tol = RealScalar(8) * static_cast<RealScalar>(n) * NumTraits<Scalar>::epsilon() * A.norm();
    VERIFY((A_hat - A).norm() < tol);
  }
}

// ---- Repeated eigenvalues ---------------------------------------------------
//
// Builds A with a degenerate eigenvalue cluster. Eigenvectors within the cluster
// are not uniquely determined, but eigenvalues, reconstruction, and orthogonality
// must still hold.

template <typename Scalar>
void test_eigen_repeated_values(Index n) {
  using Mat = Matrix<Scalar, Dynamic, Dynamic>;
  using Vec = Matrix<typename NumTraits<Scalar>::Real, Dynamic, 1>;
  using RealScalar = typename NumTraits<Scalar>::Real;

  // Build a unitary V via QR of a random matrix.
  Mat seed = Mat::Random(n, n);
  Mat V = HouseholderQR<Mat>(seed).householderQ();

  // Spectrum: a 4-fold cluster at value 1, then increasing distinct values.
  Vec eigs(n);
  for (Index i = 0; i < n; ++i) {
    eigs(i) = (i < 4) ? RealScalar(1) : RealScalar(i);
  }
  Mat A = V * eigs.asDiagonal() * V.adjoint();
  Mat A_sym = (A + A.adjoint()) * RealScalar(0.5);  // symmetrize numerically

  gpu::SelfAdjointEigenSolver<Scalar> es(A_sym);
  VERIFY_IS_EQUAL(es.info(), Success);

  // Eigenvalues must match the constructed spectrum (cuSOLVER returns ascending).
  Vec W_gpu = es.eigenvalues();
  Vec W_expected = eigs;
  std::sort(W_expected.data(), W_expected.data() + n);

  RealScalar tol_w =
      RealScalar(2) * static_cast<RealScalar>(n) * NumTraits<Scalar>::epsilon() * W_expected.cwiseAbs().maxCoeff();
  VERIFY((W_gpu - W_expected).norm() < tol_w);

  // Reconstruction must hold even with a degenerate cluster (eigenvectors form a
  // valid orthonormal basis for the cluster's invariant subspace).
  Mat V_gpu = es.eigenvectors();
  Mat A_hat = V_gpu * W_gpu.asDiagonal() * V_gpu.adjoint();
  RealScalar tol = RealScalar(20) * static_cast<RealScalar>(n) * NumTraits<Scalar>::epsilon() * A.norm();
  VERIFY((A_hat - A_sym).norm() < tol);

  // Orthogonality of computed eigenvectors must hold.
  VERIFY((V_gpu.adjoint() * V_gpu - Mat::Identity(n, n)).norm() < tol);
}

// ---- Device-side accessors --------------------------------------------------
//
// d_eigenvalues / d_eigenvectors return non-owning views over the solver's
// internal d_W_ / d_A_ buffers. Verify they agree with the host accessors and
// that repeated invocations leave the solver state intact.

template <typename Scalar>
void test_eigen_device_accessors(Index n) {
  using Mat = Matrix<Scalar, Dynamic, Dynamic>;

  Mat R = Mat::Random(n, n);
  Mat A = R + R.adjoint();

  gpu::SelfAdjointEigenSolver<Scalar> es(A);
  VERIFY_IS_EQUAL(es.info(), Success);

  auto d_W = es.d_eigenvalues();
  auto d_V = es.d_eigenvectors();

  VERIFY_IS_APPROX(d_W.toHost(), es.eigenvalues());
  VERIFY_IS_APPROX(d_V.toHost(), es.eigenvectors());

  // Re-fetch must keep working (view destruction must not free the underlying buffers).
  (void)es.d_eigenvalues();
  (void)es.d_eigenvectors();
  VERIFY_IS_APPROX(es.eigenvalues(), d_W.toHost());
  VERIFY_IS_APPROX(es.eigenvectors(), d_V.toHost());
}

// ---- Chain device views into a downstream cuBLAS GEMM (no D2D copy) ---------

template <typename Scalar>
void test_eigen_chain_orthogonality(Index n) {
  using Mat = Matrix<Scalar, Dynamic, Dynamic>;
  using RealScalar = typename NumTraits<Scalar>::Real;

  Mat R = Mat::Random(n, n);
  Mat A = R + R.adjoint();

  gpu::SelfAdjointEigenSolver<Scalar> es(A);
  VERIFY_IS_EQUAL(es.info(), Success);

  // V^H * V = I — V is the device view of d_A_; the GEMM consumes the view
  // without an intervening D2D copy.
  gpu::Context ctx;
  gpu::DeviceMatrix<Scalar> d_VtV;
  {
    auto d_V = es.d_eigenvectors();
    d_VtV.device(ctx) = d_V.adjoint() * d_V;
  }
  Mat VtV = d_VtV.toHost();
  RealScalar tol = RealScalar(20) * static_cast<RealScalar>(n) * NumTraits<Scalar>::epsilon();
  VERIFY((VtV - Mat::Identity(n, n)).norm() < tol);

  // After view destruction, the solver's state must remain valid.
  Mat V_again = es.eigenvectors();
  VERIFY_IS_EQUAL(V_again.rows(), n);
}

// ---- Move support -------------------------------------------------------------

template <typename Scalar>
void test_eigen_move(Index n) {
  using Mat = Matrix<Scalar, Dynamic, Dynamic>;
  using RealScalar = typename NumTraits<Scalar>::Real;

  Mat R = Mat::Random(n, n);
  Mat A = R + R.adjoint();

  gpu::SelfAdjointEigenSolver<Scalar> es(A);
  VERIFY_IS_EQUAL(es.info(), Success);

  gpu::SelfAdjointEigenSolver<Scalar> moved(std::move(es));
  VERIFY_IS_EQUAL(moved.info(), Success);
  Mat V = moved.eigenvectors();
  auto W = moved.eigenvalues();
  RealScalar tol = RealScalar(8) * static_cast<RealScalar>(n) * NumTraits<Scalar>::epsilon() * A.norm();
  VERIFY((V * W.asDiagonal() * V.adjoint() - A).norm() < tol);

  // Overwrite a Context-bound solver without querying its pending status
  // first. Move assignment must retire its asynchronous info copy before
  // releasing the pinned host destination.
  Mat pending_random = Mat::Random(n, n);
  Mat pending_input = pending_random + pending_random.adjoint();
  gpu::Context ctx;
  gpu::SelfAdjointEigenSolver<Scalar> assigned(ctx, pending_input);
  assigned = std::move(moved);
  VERIFY_IS_EQUAL(assigned.info(), Success);
  V = assigned.eigenvectors();
  W = assigned.eigenvalues();
  VERIFY((V * W.asDiagonal() * V.adjoint() - A).norm() < tol);

  // The borrowed Context remains usable after its old solver state is retired.
  gpu::SelfAdjointEigenSolver<Scalar> context_solver(ctx, pending_input);
  VERIFY_IS_EQUAL(context_solver.info(), Success);
}

// ---- Host getters wait only for the solver's stream -------------------------
// A download through the legacy default stream (cudaMemcpy) would also wait
// for the unrelated blocking stream parked below.

template <typename Scalar>
void test_eigen_getters_ignore_other_streams(Index n) {
  using Mat = Matrix<Scalar, Dynamic, Dynamic>;

  Mat R = Mat::Random(n, n);
  Mat A = R + R.adjoint();
  gpu::SelfAdjointEigenSolver<Scalar> es(A);
  VERIFY_IS_EQUAL(es.info(), Success);

  gpu::Context other;
  gpu_test::ParkedStream parked(other.stream());
  (void)es.eigenvalues();
  (void)es.eigenvectors();
  VERIFY(parked.held());
}

// ---- Empty matrix -----------------------------------------------------------

void test_eigen_empty() {
  ArrayXXd empty(0, 0);
  gpu::SelfAdjointEigenSolver<double> es(empty);
  VERIFY_IS_EQUAL(es.info(), Success);
  VERIFY_IS_EQUAL(es.rows(), 0);
  VERIFY_IS_EQUAL(es.cols(), 0);
}

// ---- Per-scalar driver ------------------------------------------------------

template <typename Scalar>
void test_scalar() {
  // Reconstruction + orthogonality.
  CALL_SUBTEST(test_eigen_reconstruction<Scalar>(64));
  CALL_SUBTEST(test_eigen_reconstruction<Scalar>(128));

  // Eigenvalues match CPU.
  CALL_SUBTEST(test_eigen_values<Scalar>(64));
  CALL_SUBTEST(test_eigen_values<Scalar>(128));

  // Values-only mode.
  CALL_SUBTEST(test_eigen_values_only<Scalar>(64));

  // DeviceMatrix input.
  CALL_SUBTEST(test_eigen_device_matrix<Scalar>(64));

  // Recompute.
  CALL_SUBTEST(test_eigen_recompute<Scalar>(32));

  // Repeated eigenvalues (degenerate cluster).
  CALL_SUBTEST(test_eigen_repeated_values<Scalar>(64));

  // Device accessors.
  CALL_SUBTEST(test_eigen_device_accessors<Scalar>(64));

  // Chain device view into a downstream GEMM.
  CALL_SUBTEST(test_eigen_chain_orthogonality<Scalar>(64));

  // Move constructor/assignment.
  CALL_SUBTEST(test_eigen_move<Scalar>(32));

  CALL_SUBTEST(test_eigen_getters_ignore_other_streams<Scalar>(64));
}

EIGEN_DECLARE_TEST(gpu_cusolver_eigen) {
  gpu_test::require_cuda_device();
  // Split by scalar so each part compiles in parallel.
  CALL_SUBTEST_1(test_scalar<float>());
  CALL_SUBTEST_2(test_scalar<double>());
  CALL_SUBTEST_3(test_scalar<std::complex<float>>());
  CALL_SUBTEST_4(test_scalar<std::complex<double>>());
  CALL_SUBTEST_5(test_eigen_empty());
}
