File indexing completed on 2024-05-19 03:49:02

0001 /*
0002     File                 : nsl_interp.c
0003     Project              : LabPlot
0004     Description          : NSL interpolation functions
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2016 Stefan Gerlach <stefan.gerlach@uni.kn>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "nsl_interp.h"
0012 #include "nsl_common.h"
0013 
0014 const char* nsl_interp_type_name[] = {i18n("Linear"),
0015                                       i18n("Polynomial"),
0016                                       i18n("Cubic Spline (Natural)"),
0017                                       i18n("Cubic Spline (Periodic)"),
0018                                       i18n("Akima-Spline (Natural)"),
0019                                       i18n("Akima-Spline (Periodic)"),
0020                                       i18n("Steffen-Spline"),
0021                                       i18n("Cosine"),
0022                                       i18n("Exponential"),
0023                                       i18n("Piecewise Cubic Hermite (PCH)"),
0024                                       i18n("Rational Functions")};
0025 const char* nsl_interp_pch_variant_name[] = {i18n("Finite Differences"), i18n("Catmull-Rom"), i18n("Cardinal"), i18n("Kochanek-Bartels (TCB)")};
0026 const char* nsl_interp_evaluate_name[] = {i18n("Function"), i18n("Derivative"), i18n("Second Derivative"), i18n("Integral")};
0027 
0028 int nsl_interp_ratint(const double* x, const double* y, int n, double xn, double* v, double* dv) {
0029     int i, a = 0, b = n - 1;
0030     while (b - a > 1) { /* find interval using bisection */
0031         int j = (int)floor((a + b) / 2.);
0032         if (x[j] > xn)
0033             b = j;
0034         else
0035             a = j;
0036     }
0037 
0038     int ns = a; /* nearest index */
0039     if (fabs(xn - x[a]) > fabs(xn - x[b]))
0040         ns = b;
0041 
0042     if (xn == x[ns]) { /* exact point */
0043         *v = y[ns];
0044         *dv = 0;
0045         return 1;
0046     }
0047 
0048     double* c = (double*)malloc(n * sizeof(double));
0049     double* d = (double*)malloc(n * sizeof(double));
0050     for (i = 0; i < n; i++)
0051         c[i] = d[i] = y[i];
0052 
0053     *v = y[ns--];
0054 
0055     double t, dd;
0056     int m;
0057     for (m = 1; m < n; m++) {
0058         for (i = 0; i < n - m; i++) {
0059             t = (x[i] - xn) * d[i] / (x[i + m] - xn);
0060             dd = t - c[i + 1];
0061             if (dd == 0.0) /* pole */
0062                 dd += DBL_MIN;
0063             dd = (c[i + 1] - d[i]) / dd;
0064             d[i] = c[i + 1] * dd;
0065             c[i] = t * dd;
0066         }
0067 
0068         *dv = (2 * (ns + 1) < (n - m) ? c[ns + 1] : d[ns--]);
0069         *v += *dv;
0070     }
0071 
0072     free(c);
0073     free(d);
0074 
0075     return 0;
0076 }