Blame bspline/test.c

Packit 67cb25
/* bspline/test.c
Packit 67cb25
 *
Packit 67cb25
 * Copyright (C) 2006, 2007, 2009 Brian Gough
Packit 67cb25
 * Copyright (C) 2008, 2011 Rhys Ulerich
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_test.h>
Packit 67cb25
#include <gsl/gsl_errno.h>
Packit 67cb25
#include <gsl/gsl_bspline.h>
Packit 67cb25
#include <gsl/gsl_ieee_utils.h>
Packit 67cb25
#include <gsl/gsl_nan.h>
Packit 67cb25
Packit 67cb25
void
Packit 67cb25
test_bspline(gsl_bspline_workspace * bw)
Packit 67cb25
{
Packit 67cb25
  gsl_vector *B;
Packit 67cb25
  gsl_matrix *dB;
Packit 67cb25
  size_t i, j;
Packit 67cb25
  size_t n = 100;
Packit 67cb25
  size_t ncoeffs = gsl_bspline_ncoeffs(bw);
Packit 67cb25
  size_t order = gsl_bspline_order(bw);
Packit 67cb25
  size_t nbreak = gsl_bspline_nbreak(bw);
Packit 67cb25
  double a = gsl_bspline_breakpoint(0, bw);
Packit 67cb25
  double b = gsl_bspline_breakpoint(nbreak - 1, bw);
Packit 67cb25
Packit 67cb25
  B  = gsl_vector_alloc(ncoeffs);
Packit 67cb25
  dB = gsl_matrix_alloc(ncoeffs, 1);
Packit 67cb25
Packit 67cb25
  /* Ensure B-splines form a partition of unity */
Packit 67cb25
  for (i = 0; i < n; i++)
Packit 67cb25
    {
Packit 67cb25
      double xi = a + (b - a) * (i / (n - 1.0));
Packit 67cb25
      double sum = 0;
Packit 67cb25
      gsl_bspline_eval(xi, B, bw);
Packit 67cb25
Packit 67cb25
      for (j = 0; j < ncoeffs; j++)
Packit 67cb25
        {
Packit 67cb25
          double Bj = gsl_vector_get(B, j);
Packit 67cb25
          int s = (Bj < 0 || Bj > 1);
Packit 67cb25
          gsl_test(s,
Packit 67cb25
                   "basis-spline coefficient %u is in range [0,1] for x=%g",
Packit 67cb25
                   j, xi);
Packit 67cb25
          sum += Bj;
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
      gsl_test_rel(sum, 1.0, order * GSL_DBL_EPSILON,
Packit 67cb25
                   "basis-spline order %u is normalized for x=%g", order,
Packit 67cb25
                   xi);
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* Ensure B-splines 0th derivatives agree with regular evaluation */
Packit 67cb25
  for (i = 0; i < n; i++)
Packit 67cb25
    {
Packit 67cb25
      double xi = a + (b - a) * (i / (n - 1.0));
Packit 67cb25
      gsl_bspline_eval(xi, B, bw);
Packit 67cb25
      gsl_bspline_deriv_eval(xi, 0, dB, bw);
Packit 67cb25
Packit 67cb25
      for (j = 0; j < ncoeffs; j++)
Packit 67cb25
        {
Packit 67cb25
          gsl_test_abs(gsl_matrix_get(dB, j, 0), gsl_vector_get(B, j),
Packit 67cb25
                       GSL_DBL_EPSILON,
Packit 67cb25
                       "b-spline order %d basis #%d evaluation and 0th derivative consistent for x=%g",
Packit 67cb25
                       order, j, xi);
Packit 67cb25
        }
Packit 67cb25
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  gsl_vector_free(B);
Packit 67cb25
  gsl_matrix_free(dB);
Packit 67cb25
}
Packit 67cb25
Packit 67cb25
int
Packit 67cb25
main(int argc, char **argv)
Packit 67cb25
{
Packit 67cb25
  size_t order, breakpoints, i;
Packit 67cb25
Packit 67cb25
  gsl_ieee_env_setup();
Packit 67cb25
Packit 67cb25
  argc = 0;                     /* prevent warnings about unused parameters */
Packit 67cb25
  argv = 0;
Packit 67cb25
Packit 67cb25
  for (order = 1; order < 10; order++)
Packit 67cb25
    {
Packit 67cb25
      for (breakpoints = 2; breakpoints < 100; breakpoints++)
Packit 67cb25
        {
Packit 67cb25
          double a = -1.23 * order, b = 45.6 * order;
Packit 67cb25
          gsl_bspline_workspace *bw = gsl_bspline_alloc(order, breakpoints);
Packit 67cb25
          gsl_bspline_knots_uniform(a, b, bw);
Packit 67cb25
          test_bspline(bw);
Packit 67cb25
          gsl_bspline_free(bw);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
Packit 67cb25
  for (order = 1; order < 10; order++)
Packit 67cb25
    {
Packit 67cb25
      for (breakpoints = 2; breakpoints < 100; breakpoints++)
Packit 67cb25
        {
Packit 67cb25
          double a = -1.23 * order, b = 45.6 * order;
Packit 67cb25
          gsl_bspline_workspace *bw = gsl_bspline_alloc(order, breakpoints);
Packit 67cb25
          gsl_vector *k = gsl_vector_alloc(breakpoints);
Packit 67cb25
          for (i = 0; i < breakpoints; i++)
Packit 67cb25
            {
Packit 67cb25
              double f, x;
Packit 67cb25
              f = sqrt(i / (breakpoints - 1.0));
Packit 67cb25
              x = (1 - f) * a + f * b;
Packit 67cb25
              gsl_vector_set(k, i, x);
Packit 67cb25
            };
Packit 67cb25
          gsl_bspline_knots(k, bw);
Packit 67cb25
          test_bspline(bw);
Packit 67cb25
          gsl_vector_free(k);
Packit 67cb25
          gsl_bspline_free(bw);
Packit 67cb25
        }
Packit 67cb25
    }
Packit 67cb25
Packit 67cb25
  /* Spot check known 0th, 1st, 2nd derivative
Packit 67cb25
     evaluations for a particular k = 2 case.  */
Packit 67cb25
  {
Packit 67cb25
    size_t i, j; /* looping */
Packit 67cb25
Packit 67cb25
    const double xloc[4]     =  { 0.0,  1.0,  6.0,  7.0};
Packit 67cb25
    const double deriv[4][3] =
Packit 67cb25
    {
Packit 67cb25
      { -1.0/2.0,  1.0/2.0, 0.0     },
Packit 67cb25
      { -1.0/2.0,  1.0/2.0, 0.0     },
Packit 67cb25
      {      0.0, -1.0/5.0, 1.0/5.0 },
Packit 67cb25
      {      0.0, -1.0/5.0, 1.0/5.0 }
Packit 67cb25
    };
Packit 67cb25
Packit 67cb25
    gsl_bspline_workspace *bw = gsl_bspline_alloc(2, 3);
Packit 67cb25
    gsl_matrix *dB = gsl_matrix_alloc(gsl_bspline_ncoeffs(bw),
Packit 67cb25
                                      gsl_bspline_order(bw) + 1);
Packit 67cb25
Packit 67cb25
    gsl_vector *breakpts = gsl_vector_alloc(3);
Packit 67cb25
    gsl_vector_set(breakpts, 0, 0.0);
Packit 67cb25
    gsl_vector_set(breakpts, 1, 2.0);
Packit 67cb25
    gsl_vector_set(breakpts, 2, 7.0);
Packit 67cb25
    gsl_bspline_knots(breakpts, bw);
Packit 67cb25
Packit 67cb25
Packit 67cb25
    for (i = 0; i < 4; ++i)  /* at each location */
Packit 67cb25
      {
Packit 67cb25
        /* Initialize dB with poison to ensure we overwrite it */
Packit 67cb25
        gsl_matrix_set_all(dB, GSL_NAN);
Packit 67cb25
Packit 67cb25
        gsl_bspline_deriv_eval(xloc[i], gsl_bspline_order(bw), dB, bw);
Packit 67cb25
        for (j = 0; j < gsl_bspline_ncoeffs(bw) ; ++j)
Packit 67cb25
          {
Packit 67cb25
            /* check basis function 1st deriv */
Packit 67cb25
            gsl_test_abs(gsl_matrix_get(dB, j, 1), deriv[i][j], GSL_DBL_EPSILON,
Packit 67cb25
                         "b-spline k=%d basis #%d derivative %d at x = %f",
Packit 67cb25
                         gsl_bspline_order(bw), j, 1, xloc[i]);
Packit 67cb25
          }
Packit 67cb25
        for (j = 0; j < gsl_bspline_ncoeffs(bw); ++j)
Packit 67cb25
          {
Packit 67cb25
            /* check k order basis function has k-th deriv equal to 0 */
Packit 67cb25
            gsl_test_abs(gsl_matrix_get(dB, j, gsl_bspline_order(bw)), 0.0,
Packit 67cb25
                         GSL_DBL_EPSILON,
Packit 67cb25
                         "b-spline k=%d basis #%d derivative %d at x = %f",
Packit 67cb25
                         gsl_bspline_order(bw), j, gsl_bspline_order(bw),
Packit 67cb25
                         xloc[i]);
Packit 67cb25
          }
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
    gsl_matrix_free(dB);
Packit 67cb25
    gsl_bspline_free(bw);
Packit 67cb25
    gsl_vector_free(breakpts);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* Spot check known 0th, 1st, 2nd derivative
Packit 67cb25
     evaluations for a particular k = 3 case.  */
Packit 67cb25
  {
Packit 67cb25
    size_t i, j; /* looping */
Packit 67cb25
    const double xloc[5]     =  { 0.0, 5.0, 9.0, 12.0, 15.0 };
Packit 67cb25
    const double eval[5][6]  =
Packit 67cb25
    {
Packit 67cb25
      { 4./25.,  69./100.,   3./ 20. ,  0.    , 0.   , 0.    },
Packit 67cb25
      { 0.     ,  4./21. , 143./210. ,  9./70., 0.   , 0.    },
Packit 67cb25
      { 0.     ,  0.     ,   3./ 10. ,  7./10., 0.   , 0.    },
Packit 67cb25
      { 0.     ,  0.     ,   0.      ,  3./4. , 1./4., 0.    },
Packit 67cb25
      { 0.     ,  0.     ,   0.      ,  1./3. , 5./9., 1./9. }
Packit 67cb25
    };
Packit 67cb25
    const double deriv[5][6] =
Packit 67cb25
    {
Packit 67cb25
      { -4./25.,  3./50.,   1./ 10.,  0.    , 0.    , 0.      },
Packit 67cb25
      {  0.    , -2./21.,   1./105.,  3./35., 0.    , 0.      },
Packit 67cb25
      {  0.    ,  0.    ,  -1./5.  ,  1./ 5., 0.    , 0.      },
Packit 67cb25
      {  0.    ,  0.    ,   0.     , -1./ 6., 1./6. , 0.      },
Packit 67cb25
      {  0.    ,  0.    ,   0.     , -1./ 9., 1./27., 2./27. }
Packit 67cb25
    };
Packit 67cb25
    const double deriv2[5][6] =
Packit 67cb25
    {
Packit 67cb25
      { 2./25., -17./150.,   1.0/30.0 ,  0.0     ,  0.     , 0.     },
Packit 67cb25
      { 0.    ,   1./ 42., -11.0/210.0,  1.0/35.0,  0.     , 0.     },
Packit 67cb25
      { 0.    ,   0.     ,   1.0/15.0 ,-11.0/90.0,  1./18. , 0.     },
Packit 67cb25
      { 0.    ,   0.     ,   0.0      ,  1.0/54.0, -7./162., 2./81. },
Packit 67cb25
      { 0.    ,   0.     ,   0.0      ,  1.0/54.0, -7./162., 2./81. }
Packit 67cb25
    };
Packit 67cb25
Packit 67cb25
    gsl_bspline_workspace *bw = gsl_bspline_alloc(3, 5);
Packit 67cb25
Packit 67cb25
    gsl_matrix *dB = gsl_matrix_alloc(gsl_bspline_ncoeffs(bw),
Packit 67cb25
                                      gsl_bspline_order(bw) + 1);
Packit 67cb25
Packit 67cb25
    gsl_vector *breakpts = gsl_vector_alloc(5);
Packit 67cb25
    gsl_vector_set(breakpts, 0, -3.0);
Packit 67cb25
    gsl_vector_set(breakpts, 1,  2.0);
Packit 67cb25
    gsl_vector_set(breakpts, 2,  9.0);
Packit 67cb25
    gsl_vector_set(breakpts, 3, 12.0);
Packit 67cb25
    gsl_vector_set(breakpts, 4, 21.0);
Packit 67cb25
    gsl_bspline_knots(breakpts, bw);
Packit 67cb25
Packit 67cb25
    for (i = 0; i < 5; ++i)  /* at each location */
Packit 67cb25
      {
Packit 67cb25
        /* Initialize dB with poison to ensure we overwrite it */
Packit 67cb25
        gsl_matrix_set_all(dB, GSL_NAN);
Packit 67cb25
        gsl_bspline_deriv_eval(xloc[i], gsl_bspline_order(bw), dB, bw);
Packit 67cb25
Packit 67cb25
        /* check basis function evaluation */
Packit 67cb25
        for (j = 0; j < gsl_bspline_ncoeffs(bw); ++j)
Packit 67cb25
          {
Packit 67cb25
            gsl_test_abs(gsl_matrix_get(dB, j, 0), eval[i][j], GSL_DBL_EPSILON,
Packit 67cb25
                         "b-spline k=%d basis #%d derivative %d at x = %f",
Packit 67cb25
                         gsl_bspline_order(bw), j, 0, xloc[i]);
Packit 67cb25
          }
Packit 67cb25
        /* check 1st derivative evaluation */
Packit 67cb25
        for (j = 0; j < gsl_bspline_ncoeffs(bw); ++j)
Packit 67cb25
          {
Packit 67cb25
            gsl_test_abs(gsl_matrix_get(dB, j, 1), deriv[i][j], GSL_DBL_EPSILON,
Packit 67cb25
                         "b-spline k=%d basis #%d derivative %d at x = %f",
Packit 67cb25
                         gsl_bspline_order(bw), j, 1, xloc[i]);
Packit 67cb25
          }
Packit 67cb25
        /* check 2nd derivative evaluation */
Packit 67cb25
        for (j = 0; j < gsl_bspline_ncoeffs(bw); ++j)
Packit 67cb25
          {
Packit 67cb25
            gsl_test_abs(gsl_matrix_get(dB, j, 2), deriv2[i][j], GSL_DBL_EPSILON,
Packit 67cb25
                         "b-spline k=%d basis #%d derivative %d at x = %f",
Packit 67cb25
                         gsl_bspline_order(bw), j, 2, xloc[i]);
Packit 67cb25
          }
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
    gsl_matrix_free(dB);
Packit 67cb25
    gsl_bspline_free(bw);
Packit 67cb25
    gsl_vector_free(breakpts);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* Check Greville abscissae functionality on a non-uniform k=1 */
Packit 67cb25
  {
Packit 67cb25
    size_t i; /* looping */
Packit 67cb25
Packit 67cb25
    /* Test parameters */
Packit 67cb25
    const size_t k = 1;
Packit 67cb25
    const double bpoint_data[]    = { 0.0, 0.2, 0.5, 0.75, 1.0 };
Packit 67cb25
    const size_t nbreak           = sizeof(bpoint_data)/sizeof(bpoint_data[0]);
Packit 67cb25
Packit 67cb25
    /* Expected results */
Packit 67cb25
    const double abscissae_data[] = { 0.1, 0.35, 0.625, 0.875 };
Packit 67cb25
    const size_t nabscissae       = sizeof(abscissae_data)/sizeof(abscissae_data[0]);
Packit 67cb25
Packit 67cb25
    gsl_vector_const_view bpoints = gsl_vector_const_view_array(bpoint_data, nbreak);
Packit 67cb25
    gsl_bspline_workspace *w = gsl_bspline_alloc(k, nbreak);
Packit 67cb25
    gsl_bspline_knots((const gsl_vector *) &bpoints, w);
Packit 67cb25
Packit 67cb25
    gsl_test_int(nabscissae, gsl_bspline_ncoeffs(w),
Packit 67cb25
        "b-spline k=%d number of abscissae", k);
Packit 67cb25
    for (i = 0; i < nabscissae; ++i)
Packit 67cb25
      {
Packit 67cb25
        gsl_test_abs(gsl_bspline_greville_abscissa(i, w), abscissae_data[i], 2*k*GSL_DBL_EPSILON,
Packit 67cb25
            "b-spline k=%d Greville abscissa #%d at x = %f", k, i, abscissae_data[i]);
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
    gsl_bspline_free(w);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* Check Greville abscissae functionality on a non-uniform k=2 */
Packit 67cb25
  {
Packit 67cb25
    size_t i; /* looping */
Packit 67cb25
Packit 67cb25
    /* Test parameters */
Packit 67cb25
    const size_t k = 2;
Packit 67cb25
    const double bpoint_data[]    = { 0.0, 0.2, 0.5, 0.75, 1.0 };
Packit 67cb25
    const size_t nbreak           = sizeof(bpoint_data)/sizeof(bpoint_data[0]);
Packit 67cb25
Packit 67cb25
    /* Expected results */
Packit 67cb25
    const double abscissae_data[] = { 0.0, 0.2, 0.5, 0.75, 1.0 };
Packit 67cb25
    const size_t nabscissae       = sizeof(abscissae_data)/sizeof(abscissae_data[0]);
Packit 67cb25
Packit 67cb25
    gsl_vector_const_view bpoints = gsl_vector_const_view_array(bpoint_data, nbreak);
Packit 67cb25
    gsl_bspline_workspace *w = gsl_bspline_alloc(k, nbreak);
Packit 67cb25
    gsl_bspline_knots((const gsl_vector *) &bpoints, w);
Packit 67cb25
Packit 67cb25
    gsl_test_int(nabscissae, gsl_bspline_ncoeffs(w),
Packit 67cb25
        "b-spline k=%d number of abscissae", k);
Packit 67cb25
    for (i = 0; i < nabscissae; ++i)
Packit 67cb25
      {
Packit 67cb25
        gsl_test_abs(gsl_bspline_greville_abscissa(i, w), abscissae_data[i], 2*k*GSL_DBL_EPSILON,
Packit 67cb25
            "b-spline k=%d Greville abscissa #%d at x = %f", k, i, abscissae_data[i]);
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
    gsl_bspline_free(w);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* Check Greville abscissae functionality on non-uniform k=3 */
Packit 67cb25
  {
Packit 67cb25
    size_t i; /* looping */
Packit 67cb25
Packit 67cb25
    /* Test parameters */
Packit 67cb25
    const size_t k = 3;
Packit 67cb25
    const double bpoint_data[]    = { 0.0, 0.2, 0.5, 0.75, 1.0 };
Packit 67cb25
    const size_t nbreak           = sizeof(bpoint_data)/sizeof(bpoint_data[0]);
Packit 67cb25
Packit 67cb25
    /* Expected results */
Packit 67cb25
    const double abscissae_data[] = {      0.0, 1.0/10.0, 7.0/20.0,
Packit 67cb25
                                      5.0/ 8.0, 7.0/ 8.0,      1.0 };
Packit 67cb25
    const size_t nabscissae       = sizeof(abscissae_data)/sizeof(abscissae_data[0]);
Packit 67cb25
Packit 67cb25
    gsl_vector_const_view bpoints = gsl_vector_const_view_array(bpoint_data, nbreak);
Packit 67cb25
    gsl_bspline_workspace *w = gsl_bspline_alloc(k, nbreak);
Packit 67cb25
    gsl_bspline_knots((const gsl_vector *) &bpoints, w);
Packit 67cb25
Packit 67cb25
    gsl_test_int(nabscissae, gsl_bspline_ncoeffs(w),
Packit 67cb25
        "b-spline k=%d number of abscissae", k);
Packit 67cb25
    for (i = 0; i < nabscissae; ++i)
Packit 67cb25
      {
Packit 67cb25
        gsl_test_abs(gsl_bspline_greville_abscissa(i, w), abscissae_data[i], 2*k*GSL_DBL_EPSILON,
Packit 67cb25
            "b-spline k=%d Greville abscissa #%d at x = %f", k, i, abscissae_data[i]);
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
    gsl_bspline_free(w);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* Check Greville abscissae functionality on non-uniform k=4 */
Packit 67cb25
  {
Packit 67cb25
    size_t i; /* looping */
Packit 67cb25
Packit 67cb25
    /* Test parameters */
Packit 67cb25
    const size_t k = 4;
Packit 67cb25
    const double bpoint_data[]    = { 0.0, 0.2, 0.5, 0.75, 1.0 };
Packit 67cb25
    const size_t nbreak           = sizeof(bpoint_data)/sizeof(bpoint_data[0]);
Packit 67cb25
Packit 67cb25
    /* Expected results */
Packit 67cb25
    const double abscissae_data[] = { 0.0,  1.0/15.0,  7.0/30.0,  29.0/60.0,
Packit 67cb25
                                            3.0/ 4.0, 11.0/12.0,        1.0 };
Packit 67cb25
    const size_t nabscissae       = sizeof(abscissae_data)/sizeof(abscissae_data[0]);
Packit 67cb25
Packit 67cb25
    gsl_vector_const_view bpoints = gsl_vector_const_view_array(bpoint_data, nbreak);
Packit 67cb25
    gsl_bspline_workspace *w = gsl_bspline_alloc(k, nbreak);
Packit 67cb25
    gsl_bspline_knots((const gsl_vector *) &bpoints, w);
Packit 67cb25
Packit 67cb25
    gsl_test_int(nabscissae, gsl_bspline_ncoeffs(w),
Packit 67cb25
        "b-spline k=%d number of abscissae", k);
Packit 67cb25
    for (i = 0; i < nabscissae; ++i)
Packit 67cb25
      {
Packit 67cb25
        gsl_test_abs(gsl_bspline_greville_abscissa(i, w), abscissae_data[i], 2*k*GSL_DBL_EPSILON,
Packit 67cb25
            "b-spline k=%d Greville abscissa #%d at x = %f", k, i, abscissae_data[i]);
Packit 67cb25
      }
Packit 67cb25
Packit 67cb25
    gsl_bspline_free(w);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* Knots computed from prescribed Greville abscissae for k = 4 */
Packit 67cb25
  {
Packit 67cb25
    size_t i; /* looping */
Packit 67cb25
Packit 67cb25
    /* Test parameters */
Packit 67cb25
    const size_t k = 4;
Packit 67cb25
    const double abscissae_data[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 };
Packit 67cb25
    const size_t nabscissae       = sizeof(abscissae_data)/sizeof(abscissae_data[0]);
Packit 67cb25
Packit 67cb25
    /* Expected results */
Packit 67cb25
    const double bpoint_data[]    = { 1.0, 4.0, 4.0, 4.0, 7.0 };
Packit 67cb25
    const size_t nbreak           = sizeof(bpoint_data)/sizeof(bpoint_data[0]);
Packit 67cb25
Packit 67cb25
    /* Compute knots from Greville abscissae */
Packit 67cb25
    double abserr;
Packit 67cb25
    gsl_vector_const_view abscissae
Packit 67cb25
        = gsl_vector_const_view_array(abscissae_data, nabscissae);
Packit 67cb25
    gsl_bspline_workspace *w = gsl_bspline_alloc(k, nbreak);
Packit 67cb25
    gsl_bspline_knots_greville(&abscissae.vector, w, &abserr);
Packit 67cb25
Packit 67cb25
    for (i = 0; i < nbreak; ++i)
Packit 67cb25
      {
Packit 67cb25
        gsl_test_abs(gsl_bspline_breakpoint(i,w), bpoint_data[i], GSL_DBL_EPSILON*50,
Packit 67cb25
            "b-spline k=%d knots_greville breakpoint #%d", k, i);
Packit 67cb25
      }
Packit 67cb25
    gsl_test_abs(abserr, 0.0, GSL_DBL_EPSILON*15,
Packit 67cb25
        "b-spline k=%d nbreak=%d knots_greville abserr", k, nbreak);
Packit 67cb25
Packit 67cb25
    gsl_bspline_free(w);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* Knots computed from prescribed Greville abscissae for k = 8 */
Packit 67cb25
  {
Packit 67cb25
    size_t i; /* looping */
Packit 67cb25
Packit 67cb25
    /* Test parameters */
Packit 67cb25
    const size_t k = 8;
Packit 67cb25
Packit 67cb25
    const double abscissae_data[] = { 1.0, 10.0/7, 13.0/7, 16.0/7, 22.0/7,
Packit 67cb25
                                      4.0, 34.0/7, 40.0/7, 43.0/7, 46.0/7, 7.0 };
Packit 67cb25
    const size_t nabscissae       = sizeof(abscissae_data)/sizeof(abscissae_data[0]);
Packit 67cb25
Packit 67cb25
    /* Expected results */
Packit 67cb25
    const double bpoint_data[]    = { 1.0, 4.0, 4.0, 4.0, 7.0 };
Packit 67cb25
    const size_t nbreak           = sizeof(bpoint_data)/sizeof(bpoint_data[0]);
Packit 67cb25
Packit 67cb25
    /* Compute knots from Greville abscissae */
Packit 67cb25
    double abserr;
Packit 67cb25
    gsl_vector_const_view abscissae
Packit 67cb25
        = gsl_vector_const_view_array(abscissae_data, nabscissae);
Packit 67cb25
    gsl_bspline_workspace *w = gsl_bspline_alloc(k, nbreak);
Packit 67cb25
    gsl_bspline_knots_greville(&abscissae.vector, w, &abserr);
Packit 67cb25
Packit 67cb25
    for (i = 0; i < nbreak; ++i)
Packit 67cb25
      {
Packit 67cb25
        gsl_test_abs(gsl_bspline_breakpoint(i,w), bpoint_data[i], GSL_DBL_EPSILON*50,
Packit 67cb25
            "b-spline k=%d knots_greville breakpoint #%d", k, i);
Packit 67cb25
      }
Packit 67cb25
    gsl_test_abs(abserr, 0.0, GSL_DBL_EPSILON*15,
Packit 67cb25
        "b-spline k=%d nbreak=%d knots_greville abserr", k, nbreak);
Packit 67cb25
Packit 67cb25
    gsl_bspline_free(w);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* Knots computed from prescribed Greville abscissae for k = 2 */
Packit 67cb25
  /* Not an interesting calculation but checks the k = 2 edge case */
Packit 67cb25
  {
Packit 67cb25
    size_t i; /* looping */
Packit 67cb25
Packit 67cb25
    /* Test parameters */
Packit 67cb25
    const size_t k = 2;
Packit 67cb25
    const double abscissae_data[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 };
Packit 67cb25
    const size_t nabscissae       = sizeof(abscissae_data)/sizeof(abscissae_data[0]);
Packit 67cb25
Packit 67cb25
    /* Expected results */
Packit 67cb25
    const double bpoint_data[]    = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0 };
Packit 67cb25
    const size_t nbreak           = sizeof(bpoint_data)/sizeof(bpoint_data[0]);
Packit 67cb25
Packit 67cb25
    /* Compute knots from Greville abscissae */
Packit 67cb25
    double abserr;
Packit 67cb25
    gsl_vector_const_view abscissae
Packit 67cb25
        = gsl_vector_const_view_array(abscissae_data, nabscissae);
Packit 67cb25
    gsl_bspline_workspace *w = gsl_bspline_alloc(k, nbreak);
Packit 67cb25
    gsl_bspline_knots_greville(&abscissae.vector, w, &abserr);
Packit 67cb25
Packit 67cb25
    for (i = 0; i < nbreak; ++i)
Packit 67cb25
      {
Packit 67cb25
        gsl_test_abs(gsl_bspline_breakpoint(i,w), bpoint_data[i], GSL_DBL_EPSILON,
Packit 67cb25
            "b-spline k=%d knots_greville breakpoint #%d", k, i);
Packit 67cb25
      }
Packit 67cb25
    gsl_test_abs(abserr, 0.0, GSL_DBL_EPSILON,
Packit 67cb25
        "b-spline k=%d nbreak=%d knots_greville abserr", k, nbreak);
Packit 67cb25
Packit 67cb25
    gsl_bspline_free(w);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  /* Knots computed from prescribed abscissae for edge case when nbreak = 2 */
Packit 67cb25
  {
Packit 67cb25
    size_t i; /* looping */
Packit 67cb25
Packit 67cb25
    /* Test parameters */
Packit 67cb25
    const size_t k = 4;
Packit 67cb25
    double abscissae_data[] = { 1.0, 3.0, 5.0, 7.0 };
Packit 67cb25
    const size_t nabscissae = sizeof(abscissae_data)/sizeof(abscissae_data[0]);
Packit 67cb25
Packit 67cb25
    /* Expected results */
Packit 67cb25
    const double bpoint_data[] = { 1.0, 7.0 };
Packit 67cb25
    const size_t nbreak        = sizeof(bpoint_data)/sizeof(bpoint_data[0]);
Packit 67cb25
Packit 67cb25
    /* Compute knots from Greville abscissae where abscissae are recoverable */
Packit 67cb25
    double abserr;
Packit 67cb25
    gsl_vector_view abscissae
Packit 67cb25
        = gsl_vector_view_array(abscissae_data, nabscissae);
Packit 67cb25
    gsl_bspline_workspace *w = gsl_bspline_alloc(k, nbreak);
Packit 67cb25
    gsl_bspline_knots_greville(&abscissae.vector, w, &abserr);
Packit 67cb25
Packit 67cb25
    /* Check recovery of breakpoints and abscissae */
Packit 67cb25
    for (i = 0; i < nbreak; ++i)
Packit 67cb25
      {
Packit 67cb25
        gsl_test_abs(gsl_bspline_breakpoint(i,w), bpoint_data[i], GSL_DBL_EPSILON,
Packit 67cb25
            "b-spline k=%d knots_greville breakpoint #%d", k, i);
Packit 67cb25
      }
Packit 67cb25
    gsl_test_abs(abserr, 0.0, GSL_DBL_EPSILON,
Packit 67cb25
        "b-spline k=%d nbreak=%d knots_greville abserr", k, nbreak);
Packit 67cb25
Packit 67cb25
    /* Modify interior abscissae so they cannot be recovered with nbreak = 2 */
Packit 67cb25
    /* Then recompute breakpoints and check that abserr is as expected */
Packit 67cb25
    abscissae_data[1] -= 1;
Packit 67cb25
    abscissae_data[2] += 1;
Packit 67cb25
    gsl_bspline_knots_greville(&abscissae.vector, w, &abserr);
Packit 67cb25
    for (i = 0; i < nbreak; ++i)
Packit 67cb25
      {
Packit 67cb25
        gsl_test_abs(gsl_bspline_breakpoint(i,w), bpoint_data[i], GSL_DBL_EPSILON,
Packit 67cb25
            "b-spline k=%d knots_greville breakpoint #%d", k, i);
Packit 67cb25
      }
Packit 67cb25
    gsl_test_abs(abserr, /* deliberate error */ 2.0, GSL_DBL_EPSILON,
Packit 67cb25
        "b-spline k=%d nbreak=%d knots_greville abserr large", k, nbreak);
Packit 67cb25
Packit 67cb25
    gsl_bspline_free(w);
Packit 67cb25
  }
Packit 67cb25
Packit 67cb25
  exit(gsl_test_summary());
Packit 67cb25
}