/** @file matrix.hpp
 *  @brief Function prototypes for creating tridiagonal matrices.
 *
 *
 *
 *  @author Cory Alexander Balaton (coryab)
 *  @author Janita Ovidie Sandtrøen Willumsen (janitaws)
 *  @bug No known bugs
 */
#ifndef __MATRIX__
#define __MATRIX__

#include <armadillo>
#include <omp.h>

/** @brief Create a tridiagonal matrix.
 *  
 *  create_tridiagonal creates a tridiagonal matrix by first creating a matrix,
 *  filled with zeros, of size NxN where N is the size of the main diagonal 
 *  matrix. Then it will fill all the values from the vector parameters into
 *  the matrix and return it.
 *
 *  @param a Vector for the lower diagonal of size N-1
 *  @param d Vector for the main diagonal of size N
 *  @param e Vector for the upper diagonal of size N-1
 *  
 *  @return arma::matrix
 * */
arma::mat create_tridiagonal(
    const arma::vec& a, 
    const arma::vec& d, 
    const arma::vec& e);

/** @brief Create a tridiagonal matrix.
 *
 *  This is an overload that takes doubles for the diagonals instead of 
 *  vectors. It will create 3 vectors that are filled with the signature
 *  provided in the arguments, and then call create_tridiagonal with the 
 *  vectors as the arguments.
 *
 *  @param n The dimensions of the tridiagonal matrix
 *  @param a The signature for the lower diagonal
 *  @param d The signature for the main diagonal
 *  @param e The signature for the upper diagonal
 *
 *  @return arma::matrix
 * */
arma::mat create_tridiagonal(int n, double a, double d, double e);

/** @brief Create a symmetric tridiagonal matrix.
 *
 *  create_symmetric_tridiagonal creates a symmetric tridiagonal matrix by 
 *  calling create_tridiagonal with the same signature for the off-diagonals.
 *
 *  @param n The dimensions of the tridiagonal matrix
 *  @param a The signature for the off diagonals
 *  @param d The signature for the main diagonal
 *
 *  @return arma::matrix
 * */
arma::mat create_symmetric_tridiagonal(int n, double a, double d);

/** @brief Find the off-diagonal element with the largest absolute value.
 *
 *  max_offdiag_symmetric find the element with the largest absolute value
 *  that isn't in the diagonal. Since this function assumes that the matrix
 *  that is given is symmetrical, we only need to loop through the upper 
 *  diagonals of the matrix.
 *
 *  @param A Symmetric matrix
 *  @param k Variable to store the row of the return value
 *  @param l Variable to store the column of the return value
 *
 *  @return Double
 * */
double max_offdiag_symmetric(arma::mat& A, int& k, int& l);

#endif
