#include <stdio.h>

#define ORDER	2
#define NP 		5

#define NEL	(NP-ORDER)

/*
 * Data
 */
double au[NP] = {10,2,15,18,1};

/*
 * Connectivity matrix
 */
int conmat[NEL][ORDER+1] =
{
	{0,1,2},
	{1,2,3},
	{2,3,4}
};

/*
 * Global quadratic basis functions
 */
double phi1_2(double ksi)
{
	return 2 * (ksi - 0.5) * (ksi - 1);
}

double phi2_2(double ksi)
{
	return 4 * ksi * (1 - ksi);
}

double phi3_2(double ksi)
{
	return 2 * ksi * (ksi-0.5);
}

/*
 * Global cubic basis functions
 */
#define	one_by_three	0.333333333333333
#define	two_by_three	0.666666666666666

double phi1_3(double ksi)
{
	return - 4.5 * (ksi - one_by_three) * (ksi - two_by_tree) * (ksi - 1);
}

double phi2_3(double ksi)
{
	return 13.5 * ksi * (ksi - two_by_tree) * (ksi - 1);
}

double phi3_3(double ksi)
{
	return - 13.5 * ksi * (ksi - one_by_tree) * (ksi - 1);
}

double phi4_3(double ksi)
{
	return 4.5 * ksi * (ksi - one_by_three) * (ksi - two_by_tree);
}
	
double (*basis_2[3])(double ksi) = {phi1_2, phi2_2, phi3_2};

double (*basis_3[4])(double ksi) = {phi1_3, phi2_3, phi3_3, phi4_3};

/*
 * FE interpolation
 */
double q_int(int element,double global_nodal_params[],double ksi)
{
	int i;
	double retval = 0;
	for(i=0;i<=ORDER;i++)
		retval += global_nodal_params[conmat[element][i]] * basis_2[i](ksi);
	return retval;
}

void fe_smooth(double global_nodal_params[],int el_start,int el_end,int ksi_subdiv)
{
	int el, i;
	double ksi, dksi = 1.0 / (double)ksi_subdiv;
	/* To avoid repetition of boundary points, calculate initial value once */
	printf("%g\n",q_int(el_start,global_nodal_params,0));
	for(el=el_start;el<=el_end;el+=ORDER)
		for(i=0,ksi=dksi;i<ksi_subdiv;i++,ksi+=dksi)
			printf("%g\n",q_int(el,global_nodal_params,ksi));
}

int main()
{
	fe_smooth(au,0,NEL-1,50);
	return 0;
}
