|
Packit |
67cb25 |
/* interpolation/bilinear.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 <gsl/gsl_errno.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_interp.h>
|
|
Packit |
67cb25 |
#include <gsl/gsl_interp2d.h>
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#define IDX2D(i, j, xsize, ysize) ((j) * (xsize) + (i))
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
bilinear_init(void * state, const double xa[], const double ya[],
|
|
Packit |
67cb25 |
const double za[], size_t xsize, size_t ysize)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
bilinear_eval(const void * state, const double xarr[], const double yarr[],
|
|
Packit |
67cb25 |
const double zarr[], size_t xsize, size_t ysize,
|
|
Packit |
67cb25 |
double x, double y, gsl_interp_accel * xa,
|
|
Packit |
67cb25 |
gsl_interp_accel * ya, double * z)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double xmin, xmax, ymin, ymax, zminmin, zminmax, zmaxmin, zmaxmax;
|
|
Packit |
67cb25 |
double dx, dy;
|
|
Packit |
67cb25 |
double t, u;
|
|
Packit |
67cb25 |
size_t xi, yi;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (xa != NULL)
|
|
Packit |
67cb25 |
xi = gsl_interp_accel_find(xa, xarr, xsize, x);
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
xi = gsl_interp_bsearch(xarr, x, 0, xsize - 1);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (ya != NULL)
|
|
Packit |
67cb25 |
yi = gsl_interp_accel_find(ya, yarr, ysize, y);
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
yi = gsl_interp_bsearch(yarr, y, 0, ysize - 1);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
xmin = xarr[xi];
|
|
Packit |
67cb25 |
xmax = xarr[xi + 1];
|
|
Packit |
67cb25 |
ymin = yarr[yi];
|
|
Packit |
67cb25 |
ymax = yarr[yi + 1];
|
|
Packit |
67cb25 |
zminmin = zarr[IDX2D(xi, yi, xsize, ysize)];
|
|
Packit |
67cb25 |
zminmax = zarr[IDX2D(xi, yi + 1, xsize, ysize)];
|
|
Packit |
67cb25 |
zmaxmin = zarr[IDX2D(xi + 1, yi, xsize, ysize)];
|
|
Packit |
67cb25 |
zmaxmax = zarr[IDX2D(xi + 1, yi + 1, xsize, ysize)];
|
|
Packit |
67cb25 |
dx = xmax - xmin;
|
|
Packit |
67cb25 |
dy = ymax - ymin;
|
|
Packit |
67cb25 |
t = (x - xmin)/dx;
|
|
Packit |
67cb25 |
u = (y - ymin)/dy;
|
|
Packit |
67cb25 |
*z = (1.-t)*(1.-u)*zminmin + t*(1.-u)*zmaxmin + (1.-t)*u*zminmax + t*u*zmaxmax;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
bilinear_deriv_x(const void * state, const double xarr[],
|
|
Packit |
67cb25 |
const double yarr[], const double zarr[],
|
|
Packit |
67cb25 |
size_t xsize, size_t ysize, double x, double y,
|
|
Packit |
67cb25 |
gsl_interp_accel * xa, gsl_interp_accel * ya, double * z_p)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double xmin, xmax, ymin, ymax, zminmin, zminmax, zmaxmin, zmaxmax;
|
|
Packit |
67cb25 |
double dx, dy;
|
|
Packit |
67cb25 |
double dt, u;
|
|
Packit |
67cb25 |
size_t xi, yi;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (xa != NULL)
|
|
Packit |
67cb25 |
xi = gsl_interp_accel_find(xa, xarr, xsize, x);
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
xi = gsl_interp_bsearch(xarr, x, 0, xsize - 1);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (ya != NULL)
|
|
Packit |
67cb25 |
yi = gsl_interp_accel_find(ya, yarr, ysize, y);
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
yi = gsl_interp_bsearch(yarr, y, 0, ysize - 1);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
xmin = xarr[xi];
|
|
Packit |
67cb25 |
xmax = xarr[xi + 1];
|
|
Packit |
67cb25 |
ymin = yarr[yi];
|
|
Packit |
67cb25 |
ymax = yarr[yi + 1];
|
|
Packit |
67cb25 |
zminmin = zarr[IDX2D(xi, yi, xsize, ysize)];
|
|
Packit |
67cb25 |
zminmax = zarr[IDX2D(xi, yi + 1, xsize, ysize)];
|
|
Packit |
67cb25 |
zmaxmin = zarr[IDX2D(xi + 1, yi, xsize, ysize)];
|
|
Packit |
67cb25 |
zmaxmax = zarr[IDX2D(xi + 1, yi + 1, xsize, ysize)];
|
|
Packit |
67cb25 |
dx = xmax - xmin;
|
|
Packit |
67cb25 |
dy = ymax - ymin;
|
|
Packit |
67cb25 |
dt = 1./dx; /* partial t / partial x */
|
|
Packit |
67cb25 |
u = (y - ymin)/dy;
|
|
Packit |
67cb25 |
*z_p = dt*(-(1.-u)*zminmin + (1.-u)*zmaxmin - u*zminmax + u*zmaxmax);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
bilinear_deriv_y(const void * state, const double xarr[],
|
|
Packit |
67cb25 |
const double yarr[], const double zarr[],
|
|
Packit |
67cb25 |
size_t xsize, size_t ysize, double x, double y,
|
|
Packit |
67cb25 |
gsl_interp_accel * xa, gsl_interp_accel * ya, double * z_p)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double xmin, xmax, ymin, ymax, zminmin, zminmax, zmaxmin, zmaxmax;
|
|
Packit |
67cb25 |
double dx, dy;
|
|
Packit |
67cb25 |
double t, du;
|
|
Packit |
67cb25 |
size_t xi, yi;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (xa != NULL)
|
|
Packit |
67cb25 |
xi = gsl_interp_accel_find(xa, xarr, xsize, x);
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
xi = gsl_interp_bsearch(xarr, x, 0, xsize - 1);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (ya != NULL)
|
|
Packit |
67cb25 |
yi = gsl_interp_accel_find(ya, yarr, ysize, y);
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
yi = gsl_interp_bsearch(yarr, y, 0, ysize - 1);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
xmin = xarr[xi];
|
|
Packit |
67cb25 |
xmax = xarr[xi + 1];
|
|
Packit |
67cb25 |
ymin = yarr[yi];
|
|
Packit |
67cb25 |
ymax = yarr[yi + 1];
|
|
Packit |
67cb25 |
zminmin = zarr[IDX2D(xi, yi, xsize, ysize)];
|
|
Packit |
67cb25 |
zminmax = zarr[IDX2D(xi, yi + 1, xsize, ysize)];
|
|
Packit |
67cb25 |
zmaxmin = zarr[IDX2D(xi + 1, yi, xsize, ysize)];
|
|
Packit |
67cb25 |
zmaxmax = zarr[IDX2D(xi + 1, yi + 1, xsize, ysize)];
|
|
Packit |
67cb25 |
dx = xmax - xmin;
|
|
Packit |
67cb25 |
dy = ymax - ymin;
|
|
Packit |
67cb25 |
t = (x - xmin)/dx;
|
|
Packit |
67cb25 |
du = 1./dy; /* partial u / partial y */
|
|
Packit |
67cb25 |
*z_p = du*(-(1.-t)*zminmin - t*zmaxmin + (1.-t)*zminmax + t*zmaxmax);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
bilinear_deriv2(const void * state, const double xarr[],
|
|
Packit |
67cb25 |
const double yarr[], const double zarr[],
|
|
Packit |
67cb25 |
size_t xsize, size_t ysize, double x, double y,
|
|
Packit |
67cb25 |
gsl_interp_accel * xa, gsl_interp_accel * ya, double * z_pp)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
*z_pp = 0.0;
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static int
|
|
Packit |
67cb25 |
bilinear_derivxy(const void * state, const double xarr[],
|
|
Packit |
67cb25 |
const double yarr[], const double zarr[],
|
|
Packit |
67cb25 |
size_t xsize, size_t ysize, double x, double y,
|
|
Packit |
67cb25 |
gsl_interp_accel * xa, gsl_interp_accel * ya, double * z_pp)
|
|
Packit |
67cb25 |
{
|
|
Packit |
67cb25 |
double xmin, xmax, ymin, ymax, zminmin, zminmax, zmaxmin, zmaxmax;
|
|
Packit |
67cb25 |
double dx, dy;
|
|
Packit |
67cb25 |
double dt, du;
|
|
Packit |
67cb25 |
size_t xi, yi;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (xa != NULL)
|
|
Packit |
67cb25 |
xi = gsl_interp_accel_find(xa, xarr, xsize, x);
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
xi = gsl_interp_bsearch(xarr, x, 0, xsize - 1);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
if (ya != NULL)
|
|
Packit |
67cb25 |
yi = gsl_interp_accel_find(ya, yarr, ysize, y);
|
|
Packit |
67cb25 |
else
|
|
Packit |
67cb25 |
yi = gsl_interp_bsearch(yarr, y, 0, ysize - 1);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
xmin = xarr[xi];
|
|
Packit |
67cb25 |
xmax = xarr[xi + 1];
|
|
Packit |
67cb25 |
ymin = yarr[yi];
|
|
Packit |
67cb25 |
ymax = yarr[yi + 1];
|
|
Packit |
67cb25 |
zminmin = zarr[IDX2D(xi, yi, xsize, ysize)];
|
|
Packit |
67cb25 |
zminmax = zarr[IDX2D(xi, yi + 1, xsize, ysize)];
|
|
Packit |
67cb25 |
zmaxmin = zarr[IDX2D(xi + 1, yi, xsize, ysize)];
|
|
Packit |
67cb25 |
zmaxmax = zarr[IDX2D(xi + 1, yi + 1, xsize, ysize)];
|
|
Packit |
67cb25 |
dx = xmax - xmin;
|
|
Packit |
67cb25 |
dy = ymax - ymin;
|
|
Packit |
67cb25 |
dt = 1./dx; /* partial t / partial x */
|
|
Packit |
67cb25 |
du = 1./dy; /* partial u / partial y */
|
|
Packit |
67cb25 |
*z_pp = dt*du*(zminmin-zmaxmin-zminmax+zmaxmax);
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
return GSL_SUCCESS;
|
|
Packit |
67cb25 |
}
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
static const gsl_interp2d_type bilinear_type = {
|
|
Packit |
67cb25 |
"bilinear",
|
|
Packit |
67cb25 |
2,
|
|
Packit |
67cb25 |
NULL,
|
|
Packit |
67cb25 |
&bilinear_init,
|
|
Packit |
67cb25 |
&bilinear_eval,
|
|
Packit |
67cb25 |
&bilinear_deriv_x,
|
|
Packit |
67cb25 |
&bilinear_deriv_y,
|
|
Packit |
67cb25 |
&bilinear_deriv2,
|
|
Packit |
67cb25 |
&bilinear_derivxy,
|
|
Packit |
67cb25 |
&bilinear_deriv2,
|
|
Packit |
67cb25 |
NULL
|
|
Packit |
67cb25 |
};
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
const gsl_interp2d_type * gsl_interp2d_bilinear = &bilinear_type;
|
|
Packit |
67cb25 |
|
|
Packit |
67cb25 |
#undef IDX2D
|