Blame interpolation/test2d.c

Packit 67cb25
/* interpolation/test2d.c
Packit 67cb25
 * 
Packit 67cb25
 * Copyright 2012 David Zaslavsky
Packit 67cb25
 * 
Packit 67cb25
 * This program is free software; you can redistribute it and/or modify
Packit 67cb25
 * it under the terms of the GNU General Public License as published by
Packit 67cb25
 * the Free Software Foundation; either version 3 of the License, or (at
Packit 67cb25
 * your option) any later version.
Packit 67cb25
 * 
Packit 67cb25
 * This program is distributed in the hope that it will be useful, but
Packit 67cb25
 * WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 67cb25
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 67cb25
 * General Public License for more details.
Packit 67cb25
 * 
Packit 67cb25
 * You should have received a copy of the GNU General Public License
Packit 67cb25
 * along with this program; if not, write to the Free Software
Packit 67cb25
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Packit 67cb25
 */
Packit 67cb25
Packit 67cb25
#include <config.h>
Packit 67cb25
#include <math.h>
Packit 67cb25
#include <gsl/gsl_errno.h>
Packit 67cb25
#include <gsl/gsl_ieee_utils.h>
Packit 67cb25
#include <gsl/gsl_test.h>
Packit 67cb25
#include <gsl/gsl_interp.h>
Packit 67cb25
#include <gsl/gsl_interp2d.h>
Packit 67cb25
#include <gsl/gsl_spline2d.h>
Packit 67cb25
Packit 67cb25
/* tests a single evaluator function from the low-level interface */
Packit 67cb25
static int
Packit 67cb25
test_single_low_level(
Packit 67cb25
  double (*evaluator)(const gsl_interp2d *, const double[], const double[],
Packit 67cb25
                      const double[], const double, const double,
Packit 67cb25
                      gsl_interp_accel *, gsl_interp_accel *),
Packit 67cb25
  int (*evaluator_e)(const gsl_interp2d *, const double[], const double[],
Packit 67cb25
                     const double[], const double, const double,
Packit 67cb25
                     gsl_interp_accel *, gsl_interp_accel *, double *),
Packit 67cb25
  const gsl_interp2d * interp, const double xarr[], const double yarr[],
Packit 67cb25
  const double zarr[], const double x, const double y,
Packit 67cb25
  gsl_interp_accel * xa, gsl_interp_accel * ya,
Packit 67cb25
  const double expected_results[], size_t i)
Packit 67cb25
{
Packit 67cb25
  if (expected_results != NULL)
Packit 67cb25
    {
Packit 67cb25
      int status;
Packit 67cb25
      double result = evaluator(interp, xarr, yarr, zarr, x, y, xa, ya);
Packit 67cb25
      gsl_test_rel(result, expected_results[i], 1e-10,
Packit 67cb25
                   "low level %s %d", gsl_interp2d_name(interp), i);
Packit 67cb25
Packit 67cb25
      status = evaluator_e(interp, xarr, yarr, zarr, x, y, xa, ya, &result);
Packit 67cb25
      if (status == GSL_SUCCESS)
Packit 67cb25
        {
Packit 67cb25
          gsl_test_rel(result, expected_results[i], 1e-10,
Packit 67cb25
                       "low level _e %s %d", gsl_interp2d_name(interp), i);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return 0;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* tests a single evaluator function from the high-level interface */
Packit 67cb25
static int
Packit 67cb25
test_single_high_level(
Packit 67cb25
    double (*evaluator)(const gsl_spline2d *, const double, const double,
Packit 67cb25
                        gsl_interp_accel *, gsl_interp_accel *),
Packit 67cb25
    int (*evaluator_e)(const gsl_spline2d *, const double, const double,
Packit 67cb25
                       gsl_interp_accel *, gsl_interp_accel *, double *),
Packit 67cb25
    const gsl_spline2d * interp, const double x, const double y,
Packit 67cb25
    gsl_interp_accel * xa, gsl_interp_accel * ya,
Packit 67cb25
    const double expected_results[], size_t i)
Packit 67cb25
{
Packit 67cb25
  if (expected_results != NULL)
Packit 67cb25
    {
Packit 67cb25
      int status;
Packit 67cb25
      double result = evaluator(interp, x, y, xa, ya);
Packit 67cb25
Packit 67cb25
      gsl_test_rel(result, expected_results[i], 1e-10,
Packit 67cb25
                   "high level %s %d", gsl_spline2d_name(interp), i);
Packit 67cb25
Packit 67cb25
      status = evaluator_e(interp, x, y, xa, ya, &result);
Packit 67cb25
      if (status == GSL_SUCCESS)
Packit 67cb25
        {
Packit 67cb25
          gsl_test_rel(result, expected_results[i], 1e-10,
Packit 67cb25
                       "high level _e %s %d", gsl_spline2d_name(interp), i);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return 0;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
 * Tests that a given interpolation type reproduces the data points
Packit 67cb25
 * it is given, and then tests that it correctly reproduces additional
Packit 67cb25
 * values.
Packit 67cb25
 */
Packit 67cb25
static int
Packit 67cb25
test_interp2d(
Packit 67cb25
const double xarr[], const double yarr[], const double zarr[], /* data */
Packit 67cb25
              size_t xsize, size_t ysize,                /* array sizes */
Packit 67cb25
              const double xval[], const double yval[],  /* test points */
Packit 67cb25
              const double zval[],                       /* expected results */
Packit 67cb25
              const double zxval[], const double zyval[],
Packit 67cb25
              const double zxxval[], const double zyyval[], const double zxyval[],
Packit 67cb25
              size_t test_size,                          /* number of test points */
Packit 67cb25
              const gsl_interp2d_type * T)
Packit 67cb25
{
Packit 67cb25
  gsl_interp_accel *xa = gsl_interp_accel_alloc();
Packit 67cb25
  gsl_interp_accel *ya = gsl_interp_accel_alloc();
Packit 67cb25
  int status = 0;
Packit 67cb25
  size_t xi, yi, zi, i;
Packit 67cb25
  gsl_interp2d * interp = gsl_interp2d_alloc(T, xsize, ysize);
Packit 67cb25
  gsl_spline2d * interp_s = gsl_spline2d_alloc(T, xsize, ysize);
Packit 67cb25
  unsigned int min_size = gsl_interp2d_type_min_size(T);
Packit 67cb25
Packit 67cb25
  gsl_test_int(min_size, T->min_size, "gsl_interp2d_type_min_size on %s", gsl_interp2d_name(interp));
Packit 67cb25
Packit 67cb25
  gsl_interp2d_init(interp, xarr, yarr, zarr, xsize, ysize);
Packit 67cb25
  gsl_spline2d_init(interp_s, xarr, yarr, zarr, xsize, ysize);
Packit 67cb25
Packit 67cb25
  /* First check that the interpolation reproduces the given points */
Packit 67cb25
  for (xi = 0; xi < xsize; xi++)
Packit 67cb25
    {
Packit 67cb25
      double x = xarr[xi];
Packit 67cb25
      for (yi = 0; yi < ysize; yi++)
Packit 67cb25
        {
Packit 67cb25
          double y = yarr[yi];
Packit 67cb25
          
Packit 67cb25
          zi = gsl_interp2d_idx(interp, xi, yi);
Packit 67cb25
          test_single_low_level(&gsl_interp2d_eval, &gsl_interp2d_eval_e,
Packit 67cb25
                                interp, xarr, yarr, zarr, x, y,
Packit 67cb25
                                xa, ya, zarr, zi);
Packit 67cb25
          test_single_low_level(&gsl_interp2d_eval_extrap,
Packit 67cb25
                                &gsl_interp2d_eval_e_extrap, interp,
Packit 67cb25
                                xarr, yarr, zarr, x, y, xa, ya, zarr, zi);
Packit 67cb25
          test_single_high_level(&gsl_spline2d_eval, &gsl_spline2d_eval_e,
Packit 67cb25
                                 interp_s, x, y, xa, ya, zarr, zi);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* Then check additional points provided */
Packit 67cb25
  for (i = 0; i < test_size; i++)
Packit 67cb25
    {
Packit 67cb25
      double x = xval[i];
Packit 67cb25
      double y = yval[i];
Packit 67cb25
        
Packit 67cb25
      test_single_low_level(&gsl_interp2d_eval,         &gsl_interp2d_eval_e,          interp, xarr, yarr, zarr, x, y, xa, ya, zval, i);
Packit 67cb25
      test_single_low_level(&gsl_interp2d_eval_deriv_x, &gsl_interp2d_eval_deriv_x_e,  interp, xarr, yarr, zarr, x, y, xa, ya, zxval, i);
Packit 67cb25
      test_single_low_level(&gsl_interp2d_eval_deriv_y, &gsl_interp2d_eval_deriv_y_e,  interp, xarr, yarr, zarr, x, y, xa, ya, zyval, i);
Packit 67cb25
      test_single_low_level(&gsl_interp2d_eval_deriv_xx,&gsl_interp2d_eval_deriv_xx_e, interp, xarr, yarr, zarr, x, y, xa, ya, zxxval, i);
Packit 67cb25
      test_single_low_level(&gsl_interp2d_eval_deriv_yy,&gsl_interp2d_eval_deriv_yy_e, interp, xarr, yarr, zarr, x, y, xa, ya, zyyval, i);
Packit 67cb25
      test_single_low_level(&gsl_interp2d_eval_deriv_xy,&gsl_interp2d_eval_deriv_xy_e, interp, xarr, yarr, zarr, x, y, xa, ya, zxyval, i);
Packit 67cb25
Packit 67cb25
      test_single_high_level(&gsl_spline2d_eval,         &gsl_spline2d_eval_e,          interp_s, x, y, xa, ya, zval, i);
Packit 67cb25
      test_single_high_level(&gsl_spline2d_eval_deriv_x, &gsl_spline2d_eval_deriv_x_e,  interp_s, x, y, xa, ya, zxval, i);
Packit 67cb25
      test_single_high_level(&gsl_spline2d_eval_deriv_y, &gsl_spline2d_eval_deriv_y_e,  interp_s, x, y, xa, ya, zyval, i);
Packit 67cb25
      test_single_high_level(&gsl_spline2d_eval_deriv_xx,&gsl_spline2d_eval_deriv_xx_e, interp_s, x, y, xa, ya, zxxval, i);
Packit 67cb25
      test_single_high_level(&gsl_spline2d_eval_deriv_yy,&gsl_spline2d_eval_deriv_yy_e, interp_s, x, y, xa, ya, zyyval, i);
Packit 67cb25
      test_single_high_level(&gsl_spline2d_eval_deriv_xy,&gsl_spline2d_eval_deriv_xy_e, interp_s, x, y, xa, ya, zxyval, i);
Packit 67cb25
Packit 67cb25
      test_single_low_level(&gsl_interp2d_eval_extrap, &gsl_interp2d_eval_e_extrap, interp, xarr, yarr, zarr, x, y, xa, ya, zval, i);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  gsl_interp_accel_free(xa);
Packit 67cb25
  gsl_interp_accel_free(ya);
Packit 67cb25
  gsl_interp2d_free(interp);
Packit 67cb25
  gsl_spline2d_free(interp_s);
Packit 67cb25
Packit 67cb25
  return status;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
 * Tests bilinear interpolation using a symmetric function, f(x,y)==f(y,x),
Packit 67cb25
 * and diagonal interpolation points (x,y) where x==y. If these tests don't
Packit 67cb25
 * pass, something is seriously broken.
Packit 67cb25
 */
Packit 67cb25
static int
Packit 67cb25
test_bilinear_symmetric()
Packit 67cb25
{
Packit 67cb25
  int status;
Packit 67cb25
  double xarr[] = {0.0, 1.0, 2.0, 3.0};
Packit 67cb25
  double yarr[] = {0.0, 1.0, 2.0, 3.0};
Packit 67cb25
  double zarr[] = {1.0, 1.1, 1.2, 1.3,
Packit 67cb25
                   1.1, 1.2, 1.3, 1.4,
Packit 67cb25
                   1.2, 1.3, 1.4, 1.5,
Packit 67cb25
                   1.3, 1.4, 1.5, 1.6};
Packit 67cb25
  double xval[] = {0.0, 0.5, 1.0, 1.5, 2.5, 3.0};
Packit 67cb25
  double yval[] = {0.0, 0.5, 1.0, 1.5, 2.5, 3.0};
Packit 67cb25
  double zval[] = {1.0, 1.1, 1.2, 1.3, 1.5, 1.6};
Packit 67cb25
  size_t xsize = sizeof(xarr) / sizeof(xarr[0]);
Packit 67cb25
  size_t ysize = sizeof(yarr) / sizeof(yarr[0]);
Packit 67cb25
  size_t test_size = sizeof(xval) / sizeof(xval[0]);
Packit 67cb25
Packit 67cb25
  status = test_interp2d(xarr, yarr, zarr, xsize, ysize, xval, yval, zval,
Packit 67cb25
                         NULL, NULL, NULL, NULL, NULL, test_size,
Packit 67cb25
                         gsl_interp2d_bilinear);
Packit 67cb25
  gsl_test(status, "bilinear interpolation with symmetric values");
Packit 67cb25
Packit 67cb25
  return status;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
 * Tests bilinear interpolation with an asymmetric function, f(x,y)!=f(y,x),
Packit 67cb25
 * and off-diagonal interpolation points (x,y) where x and y may or may not
Packit 67cb25
 * be equal.
Packit 67cb25
 */
Packit 67cb25
static int
Packit 67cb25
test_bilinear_asymmetric_z()
Packit 67cb25
{
Packit 67cb25
  int status;
Packit 67cb25
  double xarr[] = {0.0, 1.0, 2.0, 3.0};
Packit 67cb25
  double yarr[] = {0.0, 1.0, 2.0, 3.0};
Packit 67cb25
  double zarr[] = {1.0, 1.1, 1.2, 1.4,
Packit 67cb25
                   1.3, 1.4, 1.5, 1.7,
Packit 67cb25
                   1.5, 1.6, 1.7, 1.9,
Packit 67cb25
                   1.6, 1.9, 2.2, 2.3};
Packit 67cb25
  double xval[] = { 0.0, 0.5, 1.0, 1.5,  2.5, 3.0,
Packit 67cb25
                    1.3954, 1.6476, 0.824957,
Packit 67cb25
                    2.41108,  2.98619, 1.36485 };
Packit 67cb25
  double yval[] = {0.0, 0.5, 1.0, 1.5,  2.5, 3.0,
Packit 67cb25
                   0.265371, 2.13849, 1.62114,
Packit 67cb25
                   1.22198, 0.724681, 0.0596087 };
Packit 67cb25
Packit 67cb25
  /* results computed using Mathematica 9.0.1.0 */
Packit 67cb25
  double zval[] = {1.0, 1.2, 1.4, 1.55, 2.025, 2.3,
Packit 67cb25
                   1.2191513, 1.7242442248, 1.5067237,
Packit 67cb25
                   1.626612, 1.6146423, 1.15436761};
Packit 67cb25
  size_t xsize = sizeof(xarr) / sizeof(xarr[0]);
Packit 67cb25
  size_t ysize = sizeof(yarr) / sizeof(yarr[0]);
Packit 67cb25
  size_t test_size = sizeof(xval) / sizeof(xval[0]);
Packit 67cb25
Packit 67cb25
  status = test_interp2d(xarr, yarr, zarr, xsize, ysize, xval, yval, zval,
Packit 67cb25
                         NULL, NULL, NULL, NULL, NULL, test_size,
Packit 67cb25
                         gsl_interp2d_bilinear);
Packit 67cb25
  gsl_test(status, "bilinear interpolation with asymmetric z values");
Packit 67cb25
Packit 67cb25
  return status;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static int
Packit 67cb25
test_bicubic()
Packit 67cb25
{
Packit 67cb25
  int status;
Packit 67cb25
  double xarr[] = {0.0, 1.0, 2.0, 3.0};
Packit 67cb25
  double yarr[] = {0.0, 1.0, 2.0, 3.0};
Packit 67cb25
  double zarr[] = {1.0, 1.1, 1.2, 1.3,
Packit 67cb25
                   1.1, 1.2, 1.3, 1.4,
Packit 67cb25
                   1.2, 1.3, 1.4, 1.5,
Packit 67cb25
                   1.3, 1.4, 1.5, 1.6};
Packit 67cb25
  double xval[] = {1.0, 1.5, 2.0};
Packit 67cb25
  double yval[] = {1.0, 1.5, 2.0};
Packit 67cb25
  double zval[] = {1.2, 1.3, 1.4};
Packit 67cb25
  size_t xsize = sizeof(xarr) / sizeof(xarr[0]);
Packit 67cb25
  size_t ysize = sizeof(yarr) / sizeof(yarr[0]);
Packit 67cb25
  size_t test_size = sizeof(xval) / sizeof(xval[0]);
Packit 67cb25
Packit 67cb25
  status = test_interp2d(xarr, yarr, zarr, xsize, ysize, xval, yval, zval,
Packit 67cb25
                         NULL, NULL, NULL, NULL, NULL, test_size,
Packit 67cb25
                         gsl_interp2d_bicubic);
Packit 67cb25
  gsl_test(status, "bicubic interpolation on linear function");
Packit 67cb25
Packit 67cb25
  return status;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
static int
Packit 67cb25
test_bicubic_nonlinear()
Packit 67cb25
{
Packit 67cb25
  int status;
Packit 67cb25
  double xarr[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
Packit 67cb25
  double yarr[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0};
Packit 67cb25
  /* least common multiple of x and y */
Packit 67cb25
  double zarr[] = { 1,  2,  3,  4,  5,  6,  7,  8,
Packit 67cb25
                    2,  2,  6,  4, 10,  6, 14,  8,
Packit 67cb25
                    3,  6,  3, 12, 15,  6, 21, 24,
Packit 67cb25
                    4,  4, 12,  4, 20, 12, 28,  8,
Packit 67cb25
                    5, 10, 15, 20,  5, 30, 35, 40,
Packit 67cb25
                    6,  6,  6, 12, 30,  6, 42, 24,
Packit 67cb25
                    7, 14, 21, 28, 35, 42,  7, 56,
Packit 67cb25
                    8,  8, 24,  8, 40, 24, 56,  8};
Packit 67cb25
  double xval[] = {1.4, 2.3, 4.7, 3.3, 7.5, 6.6, 5.1};
Packit 67cb25
  double yval[] = {1.0, 1.8, 1.9, 2.5, 2.7, 4.1, 3.3};
Packit 67cb25
Packit 67cb25
  /* results computed using GSL 1D cubic interpolation twice */
Packit 67cb25
  double zval[] = { 1.4, 3.11183531264736, 8.27114315792559, 5.03218982537718,
Packit 67cb25
                    22.13230634702637, 23.63206834997871, 17.28553080971182 };
Packit 67cb25
  size_t xsize = sizeof(xarr) / sizeof(xarr[0]);
Packit 67cb25
  size_t ysize = sizeof(yarr) / sizeof(yarr[0]);
Packit 67cb25
  size_t test_size = sizeof(xval) / sizeof(xval[0]);
Packit 67cb25
Packit 67cb25
  status = test_interp2d(xarr, yarr, zarr, xsize, ysize, xval, yval, zval,
Packit 67cb25
                         NULL, NULL, NULL, NULL, NULL, test_size,
Packit 67cb25
                         gsl_interp2d_bicubic);
Packit 67cb25
  gsl_test(status, "bicubic interpolation on nonlinear symmetric function");
Packit 67cb25
Packit 67cb25
  return status;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* This function contributed by Andrew W. Steiner <awsteiner@gmail.com> */
Packit 67cb25
static int
Packit 67cb25
test_bicubic_nonlinear_nonsq()
Packit 67cb25
{
Packit 67cb25
  int status;
Packit 67cb25
  double xarr[] = {1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0};
Packit 67cb25
  double yarr[] = {1.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0};
Packit 67cb25
  double zarr[] = { 1,  2,  3,  4,  5,  6,  7,  8, 9, 10,
Packit 67cb25
                    2,  2,  6,  4, 10,  6, 14,  8, 11, 12,
Packit 67cb25
                    3,  6,  3, 12, 15,  6, 21, 24, 13, 14,
Packit 67cb25
                    4,  4, 12,  4, 20, 12, 28,  8, 15, 16,
Packit 67cb25
                    5, 10, 15, 20,  5, 30, 35, 40, 17, 18,
Packit 67cb25
                    6,  6,  6, 12, 30,  6, 42, 24, 19, 20,
Packit 67cb25
                    7, 14, 21, 28, 35, 42,  7, 56, 21, 22,
Packit 67cb25
                    8,  8, 24,  8, 40, 24, 56,  8, 23, 24};
Packit 67cb25
  double xval[] = {1.4, 2.3, 9.7, 3.3, 9.5, 6.6, 5.1};
Packit 67cb25
  double yval[] = {1.0, 1.8, 1.9, 2.5, 2.7, 4.1, 3.3};
Packit 67cb25
Packit 67cb25
  /* results computed using GSL 1D cubic interpolation twice */
Packit 67cb25
  double zval[] = { 1.4, 2.46782030941187003, 10.7717721621846465,
Packit 67cb25
                    4.80725067958096375, 11.6747032398627297,
Packit 67cb25
                    11.2619968682970111, 9.00168877916872567};
Packit 67cb25
  size_t xsize = sizeof(xarr) / sizeof(xarr[0]);
Packit 67cb25
  size_t ysize = sizeof(yarr) / sizeof(yarr[0]);
Packit 67cb25
  size_t test_size = sizeof(xval) / sizeof(xval[0]);
Packit 67cb25
Packit 67cb25
  status = test_interp2d(xarr, yarr, zarr, xsize, ysize, xval, yval, zval,
Packit 67cb25
                         NULL, NULL, NULL, NULL, NULL, test_size,
Packit 67cb25
                         gsl_interp2d_bicubic);
Packit 67cb25
  gsl_test(status, "bicubic interpolation on nonlinear symmetric function");
Packit 67cb25
Packit 67cb25
  return status;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/* runs all the tests */
Packit 67cb25
int
Packit 67cb25
test_interp2d_main(void)
Packit 67cb25
{
Packit 67cb25
  int status = 0;
Packit 67cb25
Packit 67cb25
  status += test_bilinear_symmetric();
Packit 67cb25
  status += test_bilinear_asymmetric_z();
Packit 67cb25
  status += test_bicubic();
Packit 67cb25
  status += test_bicubic_nonlinear();
Packit 67cb25
  status += test_bicubic_nonlinear_nonsq();
Packit 67cb25
Packit 67cb25
  return status;
Packit 67cb25
}