// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2022 Melven Roehrig-Zoellner <Melven.Roehrig-Zoellner@DLR.de>
// Copyright (c) 2011, Intel Corporation. All rights reserved.
//
// This file is based on the JacobiSVD_LAPACKE.h originally from Intel -
// see license notice below:
// SPDX-License-Identifier: BSD-3-Clause
/*
 Redistribution and use in source and binary forms, with or without modification,
 are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.
 * Neither the name of Intel Corporation nor the names of its contributors may
   be used to endorse or promote products derived from this software without
   specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

 ********************************************************************************
 *   Content : Eigen bindings to LAPACKe
 *    Singular Value Decomposition - SVD (divide and conquer variant)
 ********************************************************************************
*/
#ifndef EIGEN_BDCSVD_LAPACKE_H
#define EIGEN_BDCSVD_LAPACKE_H

namespace Eigen {

namespace internal {

namespace lapacke_helpers {

/** \internal Specialization for the data types supported by LAPACKe */

// defining a derived class to allow access to protected members
template <typename MatrixType_, int Options>
class BDCSVD_LAPACKE : public BDCSVD<MatrixType_, Options> {
  typedef BDCSVD<MatrixType_, Options> SVD;
  typedef typename SVD::MatrixType MatrixType;
  typedef typename SVD::Scalar Scalar;
  typedef typename SVD::RealScalar RealScalar;

 public:
  // construct this by moving from a parent object
  BDCSVD_LAPACKE(SVD&& svd) : SVD(std::move(svd)) {}

  template <typename Derived>
  void compute_impl_lapacke(const MatrixBase<Derived>& matrix, unsigned int computationOptions) {
    SVD::allocate(matrix.rows(), matrix.cols(), computationOptions);

    SVD::m_nonzeroSingularValues = SVD::m_diagSize;

    // prepare arguments to ?gesdd
    const lapack_int matrix_order = lapack_storage_of(matrix);
    const char jobz = (SVD::m_computeFullU || SVD::m_computeFullV)   ? 'A'
                      : (SVD::m_computeThinU || SVD::m_computeThinV) ? 'S'
                                                                     : 'N';
    const lapack_int u_cols = (jobz == 'A') ? to_lapack(SVD::rows()) : (jobz == 'S') ? to_lapack(SVD::diagSize()) : 1;
    const lapack_int vt_rows = (jobz == 'A') ? to_lapack(SVD::cols()) : (jobz == 'S') ? to_lapack(SVD::diagSize()) : 1;
    lapack_int ldu, ldvt;
    Scalar *u, *vt, dummy;
    MatrixType localU;
    if (SVD::computeU() && !(SVD::m_computeThinU && SVD::m_computeFullV)) {
      ldu = to_lapack(SVD::m_matrixU.outerStride());
      u = SVD::m_matrixU.data();
    } else if (SVD::computeV()) {
      localU.resize(SVD::rows(), u_cols);
      ldu = to_lapack(localU.outerStride());
      u = localU.data();
    } else {
      ldu = 1;
      u = &dummy;
    }
    MatrixType localV;
    if (SVD::computeU() || SVD::computeV()) {
      localV.resize(vt_rows, SVD::cols());
      ldvt = to_lapack(localV.outerStride());
      vt = localV.data();
    } else {
      ldvt = 1;
      vt = &dummy;
    }
    MatrixType temp;
    temp = matrix;

    // actual call to ?gesdd
    lapack_int info = gesdd(matrix_order, jobz, to_lapack(SVD::rows()), to_lapack(SVD::cols()), to_lapack(temp.data()),
                            to_lapack(temp.outerStride()), (RealScalar*)SVD::m_singularValues.data(), to_lapack(u), ldu,
                            to_lapack(vt), ldvt);

    // Check the result of the LAPACK call
    if (info < 0 || !SVD::m_singularValues.allFinite()) {
      // this includes info == -4 => NaN entry in A
      SVD::m_info = InvalidInput;
    } else if (info > 0) {
      SVD::m_info = NoConvergence;
    } else {
      SVD::m_info = Success;
      if (SVD::m_computeThinU && SVD::m_computeFullV) {
        SVD::m_matrixU = localU.leftCols(SVD::m_matrixU.cols());
      }
      if (SVD::computeV()) {
        SVD::m_matrixV = localV.adjoint().leftCols(SVD::m_matrixV.cols());
      }
    }
    SVD::m_isInitialized = true;
  }
};

template <typename MatrixType_, int Options, typename Derived>
BDCSVD<MatrixType_, Options>& BDCSVD_wrapper(BDCSVD<MatrixType_, Options>& svd, const MatrixBase<Derived>& matrix,
                                             int computationOptions) {
  // we need to move to the wrapper type and back
  BDCSVD_LAPACKE<MatrixType_, Options> tmpSvd(std::move(svd));
  tmpSvd.compute_impl_lapacke(matrix, computationOptions);
  svd = std::move(tmpSvd);
  return svd;
}

}  // end namespace lapacke_helpers

}  // end namespace internal

#define EIGEN_LAPACKE_SDD(EIGTYPE, EIGCOLROW, OPTIONS)                                           \
  template <>                                                                                    \
  template <typename Derived>                                                                    \
  inline BDCSVD<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>, OPTIONS>&        \
  BDCSVD<Matrix<EIGTYPE, Dynamic, Dynamic, EIGCOLROW, Dynamic, Dynamic>, OPTIONS>::compute_impl( \
      const MatrixBase<Derived>& matrix, unsigned int computationOptions) {                      \
    return internal::lapacke_helpers::BDCSVD_wrapper(*this, matrix, computationOptions);         \
  }

#define EIGEN_LAPACK_SDD_OPTIONS(OPTIONS)        \
  EIGEN_LAPACKE_SDD(double, ColMajor, OPTIONS)   \
  EIGEN_LAPACKE_SDD(float, ColMajor, OPTIONS)    \
  EIGEN_LAPACKE_SDD(dcomplex, ColMajor, OPTIONS) \
  EIGEN_LAPACKE_SDD(scomplex, ColMajor, OPTIONS) \
                                                 \
  EIGEN_LAPACKE_SDD(double, RowMajor, OPTIONS)   \
  EIGEN_LAPACKE_SDD(float, RowMajor, OPTIONS)    \
  EIGEN_LAPACKE_SDD(dcomplex, RowMajor, OPTIONS) \
  EIGEN_LAPACKE_SDD(scomplex, RowMajor, OPTIONS)

EIGEN_LAPACK_SDD_OPTIONS(0)
EIGEN_LAPACK_SDD_OPTIONS(ComputeThinU)
EIGEN_LAPACK_SDD_OPTIONS(ComputeThinV)
EIGEN_LAPACK_SDD_OPTIONS(ComputeFullU)
EIGEN_LAPACK_SDD_OPTIONS(ComputeFullV)
EIGEN_LAPACK_SDD_OPTIONS(ComputeThinU | ComputeThinV)
EIGEN_LAPACK_SDD_OPTIONS(ComputeFullU | ComputeFullV)
EIGEN_LAPACK_SDD_OPTIONS(ComputeThinU | ComputeFullV)
EIGEN_LAPACK_SDD_OPTIONS(ComputeFullU | ComputeThinV)

#undef EIGEN_LAPACK_SDD_OPTIONS

#undef EIGEN_LAPACKE_SDD

}  // end namespace Eigen

#endif  // EIGEN_BDCSVD_LAPACKE_H
