# 2.1.17.5.4 ocmath_1d_spline_fit

## Description

Computes a cubic spline approximation to an arbitrary set of data points. Least-squares cubic spline curve fit, automatic knot placement, one variable.

## Syntax

int ocmath_1d_spline_fit( OCMATH_START start, int nPoints, const double * pX, const double * pY, const double * pWeights, double dSmoothingFactor, int nest, double * fp, ocmath_Comm * warmstartinf, ocmath_Spline * spline )

## Parameters

start
[input] start = START_COLD(0), the function will build up the knot set starting with no interior points. No memory need be assigned to the parameter spline->n, and memory will be allocated internally to spline->c, spline->lamda, warmstartinf->ocmath_w, warmstartinf->ocmath_iw;
start = START_WARM, the function will restart the knot-placing strategy using knots found in a previous call of the function. In this case, all parameters except dSmoothingFactor must be unchanged from the previous call. This warm start can save time in searching for satisfactory value of the smoothing factor
nPoints
[input] the number of data points, nPoints >= 4
pX
[input]pointer to the value of the independent variable (abscissa) x,
these values must be supplied in strictly ascending order.
pY
[input] pointer to the value of the dependent variable (ordinate) y
pWeights
[input] pointer to the value of the weights, weights must be strictly positive.
dSmoothingFactor
[input] the smoothing factor, dSmoothingFactor >= 0
nest
[input] An over-estimate of the total number of knots of the spline returned, to indicate the storage space available to the function. nest >= 8.
In most practical situation nest=nPoints/2 will be sufficient.
Always large enough is nest = npoints + 4, the number of knots needed for interpolation (dSmoothingFactor = 0).
fp
[output] pointer to the sum of the squared weighted residuals of the computed spline approximation
warmstartinf
[output] pointer to the structure ocmath_Comm, if the warm start option is used, the structure must be left unchanged from the previous call.
spline
[output] pointer to structure ocmath_Spline, if the warm start option is used, the structure must be left unchanged from the previous call.

## Return

NE_NOERROR (code 0) --- success

NE_BAD_PARAM (error code 70) --- start has an illegal value

NE_INT_ARG_LT (error code 11) --- nPoints < 4 or nest < 8

NE_REAL_ARG_LT (error code 5) --- dSmoothingFactor < 0.0

NE_WEIGHTS_NOT_POSITIVE (error code 249) --- pWeights[i] are not strictly positive

NE_NOT_STRICTLY_INCREASING (error code 63) --- the sequence pX[i] is not strictly increasing

NE_SF_D_K_CONS (error code 277) --- when dSmoothingFactor = 0.0, nest < nPoints + 4

NE_ALLOC_FAIL (error code 73) --- memory allocation failed

NE_ENUMTYPE_WARM (error code 275) --- start is set to ocmath_Warm at the first call of this function

NE_NUM_KNOTS_1D_GT (error code 273) --- the number of knots needed is greater than nest. If nest is already large, say nest > nPoints/2, this may indicate that possibly dSmoothingFactor is too small

NE_SPLINE_COEFF_CONV (error code 263) --- the iterative process has failed to converge. Possibly dSmoothingFactor is too small

## Examples

EX1

//This example program reads in a set of data values, followed by a set of values of S. For each value
//of S it calls ocmath_1d_spline_fit to compute a spline approximation, and prints the values of the knots
//and the B-spline coefficients ci.
void ocmath_1d_spline_fit_ex1()
{
int NEST = 54;
int m = 15, r, j;
double weights[50] = {1.00, 2.00, 1.50, 1.00, 3.00, 1.00, 0.50, 1.00, 2.00, 2.50, 1.00, 3.00, 1.00, 2.00, 1.00};
double x[50] = {0.0000E+00, 5.0000E-01, 1.0000E+00, 1.5000E+00, 2.0000E+00, 2.5000E+00, 3.0000E+00, 4.0000E+00,
4.5000E+00, 5.0000E+00, 5.5000E+00, 6.0000E+00, 7.0000E+00, 7.5000E+00, 8.0000E+00};
double y[50] = {-1.1000E+00, -3.7200E-01, 4.3100E-01, 1.6900E+00, 2.1100E+00, 3.1000E+00, 4.2300E+00, 4.3500E+00,
4.8100E+00, 4.6100E+00, 4.7900E+00, 5.2300E+00, 6.3500E+00, 7.1900E+00, 7.9700E+00};
double s[3] = {1.0, 0.5, 0.1};
double fp, sp[99], txr;
OCMATH_START start;
ocmath_Comm warmstartinf;
ocmath_Spline spline;

start = START_COLD;

for(int i = 0; i < 3; i ++)
{
ocmath_1d_spline_fit(start, m, x, y, weights, s[i], NEST, &fp, &warmstartinf, &spline);

for (r=0; r<m; r++)
ocmath_1d_spline_evaluate(x[r], &sp[r*2], &spline);
for (r=0; r<m-1; r++)
{
txr = (x[r] + x[r+1]) / 2;
ocmath_1d_spline_evaluate(txr, &sp[r*2], &spline);
}

printf("\nCalling with smoothing factor s = %12.3e\n",s[i]);
printf("\nNumber of distinct knots = %ld\n\n", spline.n-6);
printf("Distinct knots located at \n\n");
for (j=3; j<spline.n-3; j++)
{
printf("%8.4f",spline.lamda[j]);
if((j-3)%6==5 || j==spline.n-4)
printf("\n");
}
printf("\n\n J B-spline coeff c\n\n");
for (j=0; j<spline.n-4; ++j)
printf(" %3ld %13.4f\n",j+1,spline.c[j]);
printf("\nWeighted sum of squared residuals fp = %12.3e\n",fp);
if (fp == 0.0)
printf("The spline is an interpolating spline\n");
if (spline.n == 8)
printf("The spline is the weighted least-squares cubic    polynomial\n");
start = START_WARM;
}
ocmath_free(spline.c);
ocmath_free(spline.lamda);
ocmath_free(warmstartinf.ocmath_w);
ocmath_free(warmstartinf.ocmath_iw);
}