prepend_to_slang_load_path (".");

require ("gslinterp");

static define make_xy_table (x, y)
{
   variable t = struct
     {
	x, y
     };
   t.x = x;
   t.y = y;
   return t;
}

static define my_interp_linear (x, xa, ya)
{
   variable o = interp_linear_init (xa, ya);
   loop (10)
     () = interp_eval (o, x);

   return interp_eval (o, x);
}

static define my_interp_linear_deriv (x, xa, ya)
{
   return interp_eval_deriv (interp_linear_init (xa, ya), x);
}

static define my_interp_linear_integ (xa, ya, a, b)
{
   return interp_eval_integ (interp_linear_init (xa, ya), a, b);
}

static define my_interp_cspline (x, xa, ya)
{
   variable o = interp_cspline_init (xa, ya);
   loop (10)
     () = interp_eval (o, x);

   return interp_eval (o, x);
}

static define my_interp_cspline_deriv (x, xa, ya)
{
   return interp_eval_deriv (interp_cspline_init (xa, ya), x);
}

static define my_interp_cspline_integ (xa, ya, a, b)
{
   return interp_eval_integ (interp_cspline_init (xa, ya), a, b);
}

static define test_interp (data_table, fun, test_table)
{
   variable y = (@fun) (test_table.x, data_table.x, data_table.y);
   variable diff_y = y - test_table.y;
   if (length (where (abs (diff_y) > 1e-10)))
     vmessage ("failed %S", fun);
}

static define test_interp_integ (data_table, fun, test_table)
{
   variable zeros = @test_table.x; zeros[*] = 0;
   variable y = (@fun) (data_table.x, data_table.y, zeros, test_table.x);
   variable diff_y = y - test_table.y;
   if (length (where (abs (diff_y) > 1e-10)))
     vmessage ("failed %S, max diff = %g", fun, max(diff_y));
}

static define test_cspline ()
{
   variable data_x = [ 0.0, 1.0, 2.0 ];
   variable data_y = [ 0.0, 1.0, 2.0 ];
   variable test_x = [ 0.0, 0.5, 1.0, 2.0 ];
   variable test_y = [ 0.0, 0.5, 1.0, 2.0 ];
   variable test_dy = [ 1.0, 1.0, 1.0, 1.0 ];
   variable test_iy = [ 0.0, 0.125, 0.5, 2.0 ];

   variable data_table = make_xy_table(data_x, data_y);
   variable test_table = make_xy_table(test_x, test_y);
   variable test_d_table = make_xy_table(test_x, test_dy);
   variable test_i_table = make_xy_table(test_x, test_iy);

   test_interp (data_table, &interp_cspline, test_table);
   test_interp (data_table, &my_interp_cspline, test_table);
   test_interp (data_table, &interp_cspline_deriv, test_d_table);
   test_interp (data_table, &my_interp_cspline_deriv, test_d_table);
   test_interp_integ (data_table, &interp_cspline_integ, test_i_table);
   test_interp_integ (data_table, &my_interp_cspline_integ, test_i_table);
}

static define test_linear ()
{
   variable data_x = [ 0.0, 1.0, 2.0, 3.0 ];
   variable data_y = [ 0.0, 1.0, 2.0, 3.0 ];
   variable test_x = [ 0.0, 0.5, 1.0, 1.5, 2.5, 3.0 ];
   variable test_y = [ 0.0, 0.5, 1.0, 1.5, 2.5, 3.0 ];
   variable test_dy = [ 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 ];
   variable test_iy = [ 0.0, 0.125, 0.5, 9.0/8.0, 25.0/8.0, 9.0/2.0 ];

   variable data_table = make_xy_table(data_x, data_y);
   variable test_table = make_xy_table(test_x, test_y);
   variable test_d_table = make_xy_table(test_x, test_dy);
   variable test_i_table = make_xy_table(test_x, test_iy);

   test_interp (data_table, &interp_linear, test_table);
   test_interp (data_table, &my_interp_linear, test_table);
   test_interp (data_table, &interp_linear_deriv, test_d_table);
   test_interp (data_table, &my_interp_linear_deriv, test_d_table);
   test_interp_integ (data_table, &interp_linear_integ, test_i_table);
   test_interp_integ (data_table, &my_interp_linear_integ, test_i_table);
}

test_cspline ();
test_linear ();

exit (0);
