/*static void Main(string[] args)
		{
			//TestTdm();
			TestSplineOnWikipediaExample();
			//TestSpline();
			//TestPerf();
		}*/

		private static void TestSpline()
		{
			int n = 6;

			// Create the data to be fitted
			float[] x = new float[n];
			float[] y = new float[n];
			Random rand = new Random(1);

			for (int i = 0; i < n; i++)
			{
				x[i] = i;
				y[i] = (float)rand.NextDouble() * 10;
			}

			// Compute the x values that we will evaluate the spline at.
			// Upsample the original data by a const factor.
			int upsampleFactor = 10;
			int nInterpolated = n * upsampleFactor;
			float[] xs = new float[nInterpolated];

			for (int i = 0; i < nInterpolated; i++)
			{
				xs[i] = (float)i * (n - 1) / (float)(nInterpolated - 1);
			}

			CubicSpline spline = new CubicSpline();
			float[] ys = spline.FitAndEval(x, y, xs, true);
			string path = @"..\..\testSpline.png";
			//PlotSplineSolution("Cubic Spline Interpolation - Random Data", x, y, xs, ys, path);
		}
		private static void TestPerf()
		{
			int n = 10000;

			// Create the data to be fitted
			float[] x = new float[n];
			float[] y = new float[n];
			Random rand = new Random(1);

			for (int i = 0; i < n; i++)
			{
				x[i] = i;
				y[i] = (float)rand.NextDouble() * 10;
			}

			// Compute the x values that we will evaluate the spline at.
			// Upsample the original data by a const factor.
			int upsampleFactor = 10;
			int nInterpolate = n * upsampleFactor;
			float[] xs = new float[nInterpolate];

			for (int i = 0; i < nInterpolate; i++)
			{
				xs[i] = (float)i / upsampleFactor;
			}

			// For perf, test multiple reps
			int reps = 100;
			DateTime start = DateTime.Now;

			for (int i = 0; i < reps; i++)
			{
				CubicSpline spline = new CubicSpline();
				float[] ys = spline.FitAndEval(x, y, xs, false);
			}

			TimeSpan duration = DateTime.Now - start;
			Console.WriteLine("CubicSpline upsample from {0:n0} to {1:n0} points took {2:0.00} ms for {3} iterations ({2:0.000} ms per iteration)", 
				n, nInterpolate, duration.TotalMilliseconds, reps, duration.TotalMilliseconds / reps);

			// Compare to NRinC
			//float[] y2 = new float[n];
			//float[] ys2 = new float[nInterpolate];
			//start = DateTime.Now;

			//for (int i = 0; i < reps; i++)
			//{
			//	CubicSplineNR.Spline(x, y, y2);
			//	CubicSplineNR.EvalSpline(x, y, y2, xs, ys2);
			//}

			//duration = DateTime.Now - start;
			//Console.WriteLine("CubicSplineNR upsample from {0:n0} to {1:n0} points took {2:0.00} ms for {3} iterations ({2:0.000} ms per iteration)",
			//	n, nInterpolate, duration.TotalMilliseconds, reps, duration.TotalMilliseconds / reps);
		}
		/// <summary>
		/// This is the Wikipedia "Spline Interpolation" article example.
		/// </summary>
		private static void TestSplineOnWikipediaExample()
		{
			// Create the test points.
			float[] x = new float[] { -1.0f, 0.0f, 3.0f };
			float[] y = new float[] { 0.5f, 0.0f, 3.0f };

			Console.WriteLine("x: {0}", ArrayUtil.ToString(x));
			Console.WriteLine("y: {0}", ArrayUtil.ToString(y));

			// Create the upsampled X values to interpolate
			int n = 20;
			float[] xs = new float[n];
			float stepSize = (x[x.Length - 1] - x[0]) / (n - 1);

			for (int i = 0; i < n; i++)
			{
				xs[i] = x[0] + i * stepSize;
			}

			// Solve
			CubicSpline spline = new CubicSpline();
			float[] ys = spline.FitAndEval(x, y, xs, false);

			Console.WriteLine("xs: {0}", ArrayUtil.ToString(xs));
			Console.WriteLine("ys: {0}", ArrayUtil.ToString(ys));

			// Plot
			string path = @"..\..\spline-wikipedia.png";
			//PlotSplineSolution("Cubic Spline Interpolation - Wikipedia Example", x, y, xs, ys, path);
		}