#pragma once

#include "BasisFunction.h"

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//--------------------------------------------------------------------------------------------------------------------
// LIBRARY FUNCTIONS 
//--------------------------------------------------------------------------------------------------------------------
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

namespace gelib
{
	using d_vector = gelib_impl::d_vector;
	using d_matrix = gelib_impl::d_matrix;

	/// <summary>
	/// Generate a matrix of expectations \f$ \mathbb{E}[\mathcal{I}_{i}(X)] \f$ for \f$ X \sim N(\mu, \sigma^{2}) \f$
	/// where each row corresponds to an input \f$ \mu \f$ value, and the i'th column corresponds to basis function  \f$  \mathcal{I}_{i}(X)  \f$ 
	/// valued 1 at the i'th gridpoint and 0 elsewhere.  \f$ \sigma \f$ is fixed throughout.
	/// </summary>
	/// <param name="output">Output matrix of expectations. With number of rows equal to to length of means vector,
	/// and number of columns equal to length of grid points vector. </param>
	/// <param name="X">Grid points that each basis function is fitted on.</param>
	/// <param name="mu">Vector of means.</param>
	/// <param name="standard_deviation">Standard deviation.</param>
	/// <param name="l">Lower limit of integral.</param>
	/// <param name="h">Upper limit of integral.</param>
	/// <param name="order">Order of polynomials used in fitting.</param>
	/// <param name="extrapolation">Extrapolation type, one of "zero", "constant", or "linear".</param>
	/// <param name="check_input">if set to <c>true</c> the function will throw exceptions on invalid input.</param>
	void basis_expectation_1d(d_matrix& output, d_vector const& grid, d_vector const& means, double sigma, double l, double h, size_t order, const std::string& extrapolation, bool check_input = true);

	const std::string basis_expectation_1d_check(d_vector const& grid, d_vector const& means, double sigma, double l, double h, size_t order, const std::string& boundaries);

	void basis_expectation_sum_1d(d_vector& output, d_matrix const& B_in, d_vector const& grid, d_vector const& means, double sigma, double l, double h, size_t order, const std::string& extrapolation, bool check_input = true);

	const std::string basis_expectation_sum_1d_check(d_matrix const& B_in, d_vector const& grid, d_vector const& means, double sigma, double l, double h, size_t order, const std::string& boundaries);
}