Blame interpolation/interp2d.c

Packit 67cb25
/* interpolation/interp2d.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 <stdlib.h>
Packit 67cb25
#include <gsl/gsl_errno.h>
Packit 67cb25
#include <gsl/gsl_math.h>
Packit 67cb25
#include <gsl/gsl_interp.h>
Packit 67cb25
#include <gsl/gsl_interp2d.h>
Packit 67cb25
Packit 67cb25
/**
Packit 67cb25
 * Triggers a GSL error if the argument is not equal to GSL_SUCCESS.
Packit 67cb25
 * If the argument is GSL_SUCCESS, this does nothing.
Packit 67cb25
 */
Packit 67cb25
#define DISCARD_STATUS(s) if ((s) != GSL_SUCCESS) { GSL_ERROR_VAL("interpolation error", (s),  GSL_NAN); }
Packit 67cb25
Packit 67cb25
#define IDX2D(i, j, w) ((j) * ((w)->xsize) + (i))
Packit 67cb25
Packit 67cb25
gsl_interp2d *
Packit 67cb25
gsl_interp2d_alloc(const gsl_interp2d_type * T, const size_t xsize,
Packit 67cb25
                   const size_t ysize)
Packit 67cb25
{
Packit 67cb25
  gsl_interp2d * interp;
Packit 67cb25
Packit 67cb25
  if (xsize < T->min_size || ysize < T->min_size)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR_NULL ("insufficient number of points for interpolation type",
Packit 67cb25
                      GSL_EINVAL);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  interp = (gsl_interp2d *) calloc(1, sizeof(gsl_interp2d));
Packit 67cb25
  if (interp == NULL)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR_NULL ("failed to allocate space for gsl_interp2d struct",
Packit 67cb25
                      GSL_ENOMEM);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  interp->type = T;
Packit 67cb25
  interp->xsize = xsize;
Packit 67cb25
  interp->ysize = ysize;
Packit 67cb25
Packit 67cb25
  if (interp->type->alloc == NULL)
Packit 67cb25
    {
Packit 67cb25
      interp->state = NULL;
Packit 67cb25
      return interp;
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  interp->state = interp->type->alloc(xsize, ysize);
Packit 67cb25
  if (interp->state == NULL)
Packit 67cb25
    {
Packit 67cb25
      free(interp);
Packit 67cb25
      GSL_ERROR_NULL ("failed to allocate space for gsl_interp2d state",
Packit 67cb25
                      GSL_ENOMEM);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return interp;
Packit 67cb25
} /* gsl_interp2d_alloc() */
Packit 67cb25
Packit 67cb25
void
Packit 67cb25
gsl_interp2d_free (gsl_interp2d * interp)
Packit 67cb25
{
Packit 67cb25
  RETURN_IF_NULL(interp);
Packit 67cb25
Packit 67cb25
  if (interp->type->free)
Packit 67cb25
    interp->type->free(interp->state);
Packit 67cb25
Packit 67cb25
  free(interp);
Packit 67cb25
} /* gsl_interp2d_free() */
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_interp2d_init (gsl_interp2d * interp, const double xarr[], const double yarr[],
Packit 67cb25
                   const double zarr[], const size_t xsize, const size_t ysize)
Packit 67cb25
{
Packit 67cb25
  size_t i;
Packit 67cb25
Packit 67cb25
  if (xsize != interp->xsize || ysize != interp->ysize)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR("data must match size of interpolation object", GSL_EINVAL);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  for (i = 1; i < xsize; i++)
Packit 67cb25
    {
Packit 67cb25
      if (xarr[i-1] >= xarr[i])
Packit 67cb25
        {
Packit 67cb25
          GSL_ERROR("x values must be strictly increasing", GSL_EINVAL);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  for (i = 1; i < ysize; i++)
Packit 67cb25
    {
Packit 67cb25
      if (yarr[i-1] >= yarr[i])
Packit 67cb25
        {
Packit 67cb25
          GSL_ERROR("y values must be strictly increasing", GSL_EINVAL);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  interp->xmin = xarr[0];
Packit 67cb25
  interp->xmax = xarr[xsize - 1];
Packit 67cb25
  interp->ymin = yarr[0];
Packit 67cb25
  interp->ymax = yarr[ysize - 1];
Packit 67cb25
Packit 67cb25
  {
Packit 67cb25
    int status = interp->type->init(interp->state, xarr, yarr, zarr,
Packit 67cb25
                                    xsize, ysize);
Packit 67cb25
    return status;
Packit 67cb25
  }
Packit 67cb25
} /* gsl_interp2d_init() */
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
 * A wrapper function that checks boundary conditions, calls an evaluator
Packit 67cb25
 * which implements the actual calculation of the function value or 
Packit 67cb25
 * derivative etc., and checks the return status.
Packit 67cb25
 */
Packit 67cb25
static int
Packit 67cb25
interp2d_eval(int (*evaluator)(const void *, const double xa[], const double ya[],
Packit 67cb25
                               const double za[], size_t xsize, size_t ysize,
Packit 67cb25
                               double x, double y, gsl_interp_accel *,
Packit 67cb25
                               gsl_interp_accel *, double * z),
Packit 67cb25
              const gsl_interp2d * interp, const double xarr[],
Packit 67cb25
              const double yarr[], const double zarr[],
Packit 67cb25
              const double x, const double y,
Packit 67cb25
              gsl_interp_accel * xa, gsl_interp_accel * ya,
Packit 67cb25
              double * result)
Packit 67cb25
{
Packit 67cb25
  if (x < interp->xmin || x > interp->xmax)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("interpolation x value out of range", GSL_EDOM);
Packit 67cb25
    }
Packit 67cb25
  else if (y < interp->ymin || y > interp->ymax)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("interpolation y value out of range", GSL_EDOM);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  return evaluator(interp->state, xarr, yarr, zarr,
Packit 67cb25
                   interp->xsize, interp->ysize,
Packit 67cb25
                   x, y, xa, ya, result);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
/*
Packit 67cb25
 * Another wrapper function that serves as a drop-in replacement for
Packit 67cb25
 * interp2d_eval but does not check the bounds. This can be used
Packit 67cb25
 * for extrapolation.
Packit 67cb25
 */
Packit 67cb25
static int
Packit 67cb25
interp2d_eval_extrap(int (*evaluator)(const void *, const double xa[],
Packit 67cb25
                                      const double ya[], const double za[],
Packit 67cb25
                                      size_t xsize, size_t ysize,
Packit 67cb25
                                      double x, double y,
Packit 67cb25
                                      gsl_interp_accel *,
Packit 67cb25
                                      gsl_interp_accel *, double * z),
Packit 67cb25
                     const gsl_interp2d * interp, const double xarr[],
Packit 67cb25
                     const double yarr[], const double zarr[],
Packit 67cb25
                     const double x, const double y,
Packit 67cb25
                     gsl_interp_accel * xa, gsl_interp_accel * ya,
Packit 67cb25
                     double * result)
Packit 67cb25
{
Packit 67cb25
  return evaluator(interp->state, xarr, yarr, zarr,
Packit 67cb25
                   interp->xsize, interp->ysize, x, y, xa, ya, result);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_interp2d_eval (const gsl_interp2d * interp, const double xarr[],
Packit 67cb25
                   const double yarr[], const double zarr[],
Packit 67cb25
                   const double x, const double y,
Packit 67cb25
                   gsl_interp_accel * xa, gsl_interp_accel * ya)
Packit 67cb25
{
Packit 67cb25
  double z;
Packit 67cb25
  int status = gsl_interp2d_eval_e(interp, xarr, yarr, zarr, x, y, xa, ya, &z);
Packit 67cb25
  DISCARD_STATUS(status)
Packit 67cb25
  return z;
Packit 67cb25
} /* gsl_interp2d_eval() */
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_interp2d_eval_extrap (const gsl_interp2d * interp,
Packit 67cb25
                          const double xarr[],
Packit 67cb25
                          const double yarr[],
Packit 67cb25
                          const double zarr[],
Packit 67cb25
                          const double x,
Packit 67cb25
                          const double y,
Packit 67cb25
                          gsl_interp_accel * xa,
Packit 67cb25
                          gsl_interp_accel * ya)
Packit 67cb25
{
Packit 67cb25
  double z;
Packit 67cb25
  int status =
Packit 67cb25
    interp2d_eval_extrap(interp->type->eval, interp,
Packit 67cb25
                         xarr, yarr, zarr, x, y, xa, ya, &z);
Packit 67cb25
  DISCARD_STATUS(status)
Packit 67cb25
  return z;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_interp2d_eval_e (const gsl_interp2d * interp, const double xarr[],
Packit 67cb25
                     const double yarr[], const double zarr[],
Packit 67cb25
                     const double x, const double y,
Packit 67cb25
                     gsl_interp_accel * xa, gsl_interp_accel * ya, double * z)
Packit 67cb25
{
Packit 67cb25
  return interp2d_eval(interp->type->eval, interp,
Packit 67cb25
                       xarr, yarr, zarr, x, y, xa, ya, z);
Packit 67cb25
} /* gsl_interp2d_eval_e() */
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_interp2d_eval_e_extrap (const gsl_interp2d * interp,
Packit 67cb25
                            const double xarr[], const double yarr[],
Packit 67cb25
                            const double zarr[], const double x,
Packit 67cb25
                            const double y, gsl_interp_accel * xa,
Packit 67cb25
                            gsl_interp_accel * ya, double * z)
Packit 67cb25
{
Packit 67cb25
  return interp2d_eval_extrap(interp->type->eval, interp,
Packit 67cb25
                              xarr, yarr, zarr, x, y, xa, ya, z);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_interp2d_eval_deriv_x (const gsl_interp2d * interp, const double xarr[],
Packit 67cb25
                           const double yarr[], const double zarr[],
Packit 67cb25
                           const double x, const double y,
Packit 67cb25
                           gsl_interp_accel * xa, gsl_interp_accel * ya)
Packit 67cb25
{
Packit 67cb25
  double z;
Packit 67cb25
  int status = gsl_interp2d_eval_deriv_x_e(interp, xarr, yarr, zarr, x, y, xa, ya, &z);
Packit 67cb25
  DISCARD_STATUS(status)
Packit 67cb25
  return z;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_interp2d_eval_deriv_x_e (const gsl_interp2d * interp, const double xarr[],
Packit 67cb25
                             const double yarr[], const double zarr[],
Packit 67cb25
                             const double x, const double y,
Packit 67cb25
                             gsl_interp_accel * xa, gsl_interp_accel * ya, double * z)
Packit 67cb25
{
Packit 67cb25
  return interp2d_eval(interp->type->eval_deriv_x, interp,
Packit 67cb25
                       xarr, yarr, zarr, x, y, xa, ya, z);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_interp2d_eval_deriv_y (const gsl_interp2d * interp, const double xarr[],
Packit 67cb25
                           const double yarr[], const double zarr[],
Packit 67cb25
                           const double x, const double y,
Packit 67cb25
                           gsl_interp_accel * xa, gsl_interp_accel * ya)
Packit 67cb25
{
Packit 67cb25
  double z;
Packit 67cb25
  int status = gsl_interp2d_eval_deriv_y_e(interp, xarr, yarr, zarr, x, y, xa, ya, &z);
Packit 67cb25
  DISCARD_STATUS(status)
Packit 67cb25
  return z;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_interp2d_eval_deriv_y_e (const gsl_interp2d * interp, const double xarr[],
Packit 67cb25
                             const double yarr[], const double zarr[],
Packit 67cb25
                             const double x, const double y,
Packit 67cb25
                             gsl_interp_accel * xa, gsl_interp_accel * ya, double * z)
Packit 67cb25
{
Packit 67cb25
  return interp2d_eval(interp->type->eval_deriv_y, interp,
Packit 67cb25
                       xarr, yarr, zarr, x, y, xa, ya, z);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_interp2d_eval_deriv_xx (const gsl_interp2d * interp, const double xarr[],
Packit 67cb25
                            const double yarr[], const double zarr[],
Packit 67cb25
                            const double x, const double y,
Packit 67cb25
                            gsl_interp_accel * xa, gsl_interp_accel * ya)
Packit 67cb25
{
Packit 67cb25
  double z;
Packit 67cb25
  int status = gsl_interp2d_eval_deriv_xx_e(interp, xarr, yarr, zarr, x, y, xa, ya, &z);
Packit 67cb25
  DISCARD_STATUS(status)
Packit 67cb25
  return z;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_interp2d_eval_deriv_xx_e (const gsl_interp2d * interp, const double xarr[],
Packit 67cb25
                              const double yarr[], const double zarr[],
Packit 67cb25
                              const double x, const double y,
Packit 67cb25
                              gsl_interp_accel * xa, gsl_interp_accel * ya, double * z)
Packit 67cb25
{
Packit 67cb25
  return interp2d_eval(interp->type->eval_deriv_xx, interp,
Packit 67cb25
                       xarr, yarr, zarr, x, y, xa, ya, z);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_interp2d_eval_deriv_yy (const gsl_interp2d * interp, const double xarr[],
Packit 67cb25
                            const double yarr[], const double zarr[],
Packit 67cb25
                            const double x, const double y,
Packit 67cb25
                            gsl_interp_accel * xa, gsl_interp_accel * ya)
Packit 67cb25
{
Packit 67cb25
  double z;
Packit 67cb25
  int status = gsl_interp2d_eval_deriv_yy_e(interp, xarr, yarr, zarr, x, y, xa, ya, &z);
Packit 67cb25
  DISCARD_STATUS(status)
Packit 67cb25
  return z;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_interp2d_eval_deriv_yy_e (const gsl_interp2d * interp, const double xarr[],
Packit 67cb25
                              const double yarr[], const double zarr[],
Packit 67cb25
                              const double x, const double y,
Packit 67cb25
                              gsl_interp_accel * xa, gsl_interp_accel * ya, double * z)
Packit 67cb25
{
Packit 67cb25
  return interp2d_eval(interp->type->eval_deriv_yy, interp,
Packit 67cb25
                       xarr, yarr, zarr, x, y, xa, ya, z);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_interp2d_eval_deriv_xy (const gsl_interp2d * interp, const double xarr[],
Packit 67cb25
                            const double yarr[], const double zarr[],
Packit 67cb25
                            const double x, const double y,
Packit 67cb25
                            gsl_interp_accel * xa, gsl_interp_accel * ya)
Packit 67cb25
{
Packit 67cb25
  double z;
Packit 67cb25
  int status = gsl_interp2d_eval_deriv_xy_e(interp, xarr, yarr, zarr, x, y, xa, ya, &z);
Packit 67cb25
  DISCARD_STATUS(status)
Packit 67cb25
  return z;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_interp2d_eval_deriv_xy_e (const gsl_interp2d * interp, const double xarr[],
Packit 67cb25
                              const double yarr[], const double zarr[],
Packit 67cb25
                              const double x, const double y,
Packit 67cb25
                              gsl_interp_accel * xa, gsl_interp_accel * ya, double * z)
Packit 67cb25
{
Packit 67cb25
  return interp2d_eval(interp->type->eval_deriv_xy, interp,
Packit 67cb25
                       xarr, yarr, zarr, x, y, xa, ya, z);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
size_t
Packit 67cb25
gsl_interp2d_type_min_size(const gsl_interp2d_type * T)
Packit 67cb25
{
Packit 67cb25
  return T->min_size;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
size_t
Packit 67cb25
gsl_interp2d_min_size(const gsl_interp2d * interp)
Packit 67cb25
{
Packit 67cb25
  return interp->type->min_size;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
const char *
Packit 67cb25
gsl_interp2d_name(const gsl_interp2d * interp)
Packit 67cb25
{
Packit 67cb25
  return interp->type->name;
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
size_t
Packit 67cb25
gsl_interp2d_idx(const gsl_interp2d * interp,
Packit 67cb25
                 const size_t i, const size_t j)
Packit 67cb25
{
Packit 67cb25
  if (i >= interp->xsize)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR_VAL ("x index out of range", GSL_ERANGE, 0);
Packit 67cb25
    }
Packit 67cb25
  else if (j >= interp->ysize)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR_VAL ("y index out of range", GSL_ERANGE, 0);
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      return IDX2D(i, j, interp);
Packit 67cb25
    }
Packit 67cb25
} /* gsl_interp2d_idx() */
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
gsl_interp2d_set(const gsl_interp2d * interp, double zarr[],
Packit 67cb25
                 const size_t i, const size_t j, const double z)
Packit 67cb25
{
Packit 67cb25
  if (i >= interp->xsize)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("x index out of range", GSL_ERANGE);
Packit 67cb25
    }
Packit 67cb25
  else if (j >= interp->ysize)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR ("y index out of range", GSL_ERANGE);
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      zarr[IDX2D(i, j, interp)] = z;
Packit 67cb25
      return GSL_SUCCESS;
Packit 67cb25
    }
Packit 67cb25
} /* gsl_interp2d_set() */
Packit 67cb25
Packit 67cb25
double
Packit 67cb25
gsl_interp2d_get(const gsl_interp2d * interp, const double zarr[],
Packit 67cb25
                 const size_t i, const size_t j)
Packit 67cb25
{
Packit 67cb25
  if (i >= interp->xsize)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR_VAL ("x index out of range", GSL_ERANGE, 0);
Packit 67cb25
    }
Packit 67cb25
  else if (j >= interp->ysize)
Packit 67cb25
    {
Packit 67cb25
      GSL_ERROR_VAL ("y index out of range", GSL_ERANGE, 0);
Packit 67cb25
    }
Packit 67cb25
  else
Packit 67cb25
    {
Packit 67cb25
      return zarr[IDX2D(i, j, interp)];
Packit 67cb25
    }
Packit 67cb25
} /* gsl_interp2d_get() */
Packit 67cb25
Packit 67cb25
#undef IDX2D