/** @file jacobi.hpp
 *  @brief Function prototypes for the jacobi rotation algorithm.
 *
 *  @author Cory Alexander Balaton (coryab)
 *  @author Janita Ovidie Sandtrøen Willumsen (janitaws)
 *  @bug No known bugs
 */
#ifndef __JACOBI__
#define __JACOBI__

#include <armadillo>

/** @brief Computes a single rotation.
 *
 *  jacobi_rotate computes a single rotation for Jacobi's rotation algorithm.
 *  It starts by calculating tau, t (tan), c (cos), s (sin) and then
 *  updates A and R at rows/columsn k and l.
 *
 *  @param A Matrix A<sup> (m) </sup>
 *  @param R The rotation matrix R<sup> (m) </sup>
 *  @param k Index of the row with the element of largest absolute value
 *  @param l Index of the column with the element of largest absolute value
 *
 *  @return Void
 */
void jacobi_rotate(arma::mat& A, arma::mat& R, int k, int l);

/** @brief Solves the eigenvalue problem using the jacobi rotation method.
 *
 *  jacobi_eigensolver Initializes matrices A_m and R before going into the
 *  main loop.
 *
 *  For each iteration of the loop, it finds the largest absolute off-diagonal 
 *  value of A_m, and then calls jacobi_rotate. The loop stops when the largest
 *  off-diagonal is less than the tolerance (eps) or if the maximum number of
 *  iterations has been reached.
 *
 *  The last thing this function does is to sort the eigenvalues and the
 *  corresponding eigenvectors in ascending order.
 *
 *  @param A The initial matrix to be solved
 *  @param eps Tolerance
 *  @param eigenvalues A vector that will contain the computed eigenvalues
 *  @param eigenvectors A Matrix that will contain the computed eigenvectors
 *  @param maxiter The max number of iterations allowed
 *  @param iterations To keep track of how many iterations the algorithm used
 *  @param converged Tells the user if the algorithm has converged
 *
 *  @return Void
 * */
void jacobi_eigensolver(const arma::mat& A, 
                        double eps, 
                        arma::vec& eigenvalues, 
                        arma::mat& eigenvectors, 
                        const int maxiter, 
                        int& iterations, 
                        bool& converged);

#endif
