#ifndef BSP_3_LIB_BENCH_H_INCLUDED
#define BSP_3_LIB_BENCH_H_INCLUDED

#include <vector>

/** 	Inner product
	@param[in] x	vector
	@param[in] y	vector
	@return 	    resulting Euclidean inner product <x,y>
*/
double scalar(std::vector<double> const &x, std::vector<double> const &y);


/** 	Inner product with cblas
	@param[in] x	vector
	@param[in] y	vector
	@return 	    resulting Euclidean inner product <x,y>
*/
double scalar_cblas(std::vector<double> const &x, std::vector<double> const &y);


/** 	Inner product with Kahan summation
	@param[in] x	vector
	@param[in] y	vector
	@return 	    resulting Euclidean inner product <x,y>
*/
double scalar_kahan(std::vector<double> const &x, std::vector<double> const &y);


/** 	euclidean norm
	@param[in] x	vector
	@return 	    resulting Euclidean norm
*/
double norm_eucl(std::vector<double> const &x);


/** \brief Matrix-Vektor-Multiplikation (row-wise access)
 *
 * \param[in]   a   Matrix with row wise access
 * \param[in]   x   vector which gets multiplied
 * \return          resulting product a*x (vector)
 *
 */
std::vector<double> MatVec(std::vector<double> const & a, std::vector<double> const & x);


/** \brief Matrix-Vektor-Multiplikation mit cblas (row-wise access)
 *
 * \param[in]   a   Matrix with row wise access
 * \param[in]   x   vector which gets multiplied
 * \return          resulting product a*x (vector)
 *
 */
std::vector<double> MatVec_cblas(std::vector<double> const & a, std::vector<double> const & x);


/** \brief Matrix-Vektor-Multiplikation (column-wise access)
 *
 * \param[in]   a   Matrix with row wise access
 * \param[in]   x   vector which gets multiplied
 * \return          resulting product a*x (vector)
 *
 */
std::vector<double> MatVec_column(std::vector<double> const & a, std::vector<double> const & x);


/** \brief Matrix-Matrix-Multiplikation (row-wise access)
 *
 * \param[in]   a   matrix with row wise access (M*L)
 * \param[in]   b   matrix with row wise access (L*N)
 * \param[in]   L   inner dimension of the matrix product
 * \return          resulting product a*b
 *
 */
std::vector<double> MatMatProd(std::vector<double> const & a, std::vector<double> const & b, int const & L);


/** \brief Matrix-Matrix-Multiplikation mit cblas (row-wise access)
 *
 * \param[in]   a   matrix with row wise access (M*L)
 * \param[in]   b   matrix with row wise access (L*N)
 * \param[in]   L   inner dimension of the matrix product
 * \return          resulting product a*b
 *
 */
std::vector<double> MatMatProd_cblas(std::vector<double> const & a, std::vector<double> const & b, int const & L);


/** \brief Polynomauswertung an Stelle x
 *
 * \param[in]   a   Vekor mit den Koeffizienten des Polynoms a=[a0,a1,a2,...]
 * \param[in]   x   Vektor, für welchen das Polynom ausgewertet werden soll
 * \return          resulting vector p(x)
 *
 */
std::vector<double> PolynomEval(std::vector<double> const & a, std::vector<double> const & x);


/** \brief Benchmarking A - the scalar product
 *
 * \param   N   size of the vector
 * \param   Nloops  number of iterations we want to do for the measuring
 *
 */
void benchmark_A(int const & N, int const & Nloops);


/** \brief Benchmarking A - the scalar product with cblas
 *
 * \param   N   size of the vector
 * \param   Nloops  number of iterations we want to do for the measuring
 *
 */
void benchmark_A_cblas(int const & N, int const & Nloops);



/** \brief Benchmarking A - the scalar product with Kahan summation
 *
 * \param   N   size of the vector
 * \param   Nloops  number of iterations we want to do for the measuring
 *
 */
void benchmark_A_kahan(int const & N, int const & Nloops);


/** \brief Benchmarking A - norm
 *
 * \param   N   size of the vector
 * \param   Nloops  number of iterations we want to do for the measuring
 *
 */
void benchmark_A_norm(int const & N, int const & Nloops);


/** \brief Benchmarking B - matrix-vector product Ax=b (row wise access)
 *
 * \param   N   size of vector x
 * \param   M   size of vector b (=> A: M*N)
 * \param   Nloops  number of iterations we want to do for the measuring
 *
 */
void benchmark_B(int const & N, int const & M, int const & Nloops);


/** \brief Benchmarking B - matrix-vector product Ax=b with cblas (row wise access)
 *
 * \param   N   size of vector x
 * \param   M   size of vector b (=> A: M*N)
 * \param   Nloops  number of iterations we want to do for the measuring
 *
 */
void benchmark_B_cblas(int const & N, int const & M, int const & Nloops);


/** \brief Benchmarking B - matrix-vector product Ax=b (column wise access)
 *
 * \param   N   size of vector x
 * \param   M   size of vector b (=> A: M*N)
 * \param   Nloops  number of iterations we want to do for the measuring
 *
 */
void benchmark_B_column(int const & N, int const & M, int const & Nloops);


/** \brief Benchmarking C - Matrix-Matrix product C=A*B A_M*L, B_L*N
 *
 * \param   N
 * \param   M
 * \param   L
 * \param   Nloops  number of iterations we want to do for the measuring
 *
 */
void benchmark_C(int const & N, int const & M, int const & L, int const & Nloops);


/** \brief Benchmarking C - Matrix-Matrix product with cblas; C=A*B A_M*L, B_L*N
 *
 * \param   N
 * \param   M
 * \param   L
 * \param   Nloops  number of iterations we want to do for the measuring
 *
 */
void benchmark_C_cblas(int const & N, int const & M, int const & L, int const & Nloops);


/** \brief Benchmarking D - polynomial evaluation
 *
 * \param   p   the degree of the polynomial
 * \param   N   size of the input vector x where p(x)
 * \param   Nloops  number of iterations we want to do for the measuring
 *
 */
void benchmark_D(int const & p, int const & N, int const & Nloops);


/** \brief solving system of linear equations with time measurement
 *
 * \param   N   size of the system Ax=b with A(nxn)
 * \param	nrhs	number of right hand sides b(nxnrhs)
 *
 */
void solver(int const & N, int const & nrhs);
#endif // BSP_3_LIB_BENCH_H_INCLUDED
