23#include <gsl/gsl_errno.h>
24#include <gsl/gsl_fit.h>
25#include <gsl/gsl_multifit.h>
26#include <gsl/gsl_min.h>
27#include <gsl/gsl_nan.h>
28#include <gsl/gsl_poly.h>
29#include <gsl/gsl_sf_trig.h>
30#include <gsl/gsl_statistics.h>
31#include <gsl/gsl_version.h>
33#include <lal/TriggerInterpolate.h>
35#define STRINGIZE(s) #s
44static void unwrap(
double *arg,
size_t n)
48 for (
size_t i = 1; i < n; i ++)
50 double next = arg[i], delta = next - prev;
54 else if (delta < -M_PI)
56 arg[i] += winds * 2 * M_PI;
65 for (
size_t i = 0; i < n; i ++)
79 for (; n > 0 &&
a[n - 1] == 0; n--)
87static void poly_mac(
double *
y,
const double *
a,
size_t na,
const double *b,
size_t nb)
90 for (
size_t ia = 0; ia < na; ia++)
91 for (
size_t ib = 0; ib < nb; ib++)
92 y[ia + ib] +=
a[ia] * b[ib];
98static void poly_der(
double *
y,
const double *
a,
size_t n)
100 for (
size_t i = 0; i < n - 1; i ++)
101 y[i] = (i + 1) *
a[i + 1];
108 a[3] = 0.5 * (
y[3] -
y[0]) + 1.5 * (
y[1] -
y[2]);
109 a[2] =
y[0] - 2.5 *
y[1] + 2 *
y[2] - 0.5 *
y[3];
110 a[1] = 0.5 * (
y[2] -
y[0]);
131 *nroots = gsl_poly_solve_quadratic(
140 *nroots = gsl_poly_solve_cubic(
141 a[2] /
a[3],
a[1] /
a[3],
a[0] /
a[3],
142 &
r[0], &
r[1], &
r[2]);
149 double complex complex_roots[n - 1];
150 double workspace_matrix[n - 1][n - 1];
151 gsl_poly_complex_workspace workspace = {n - 1, *workspace_matrix};
153 int result = gsl_poly_complex_solve(
a, n, &workspace,
154 (gsl_complex_packed_ptr) complex_roots);
156 if (result == GSL_SUCCESS)
159 for (
size_t i = 0; i + 1 < n; i ++)
160 if (cimag(complex_roots[i]) == 0)
161 r[(*nroots)++] = creal(complex_roots[i]);
174static int poly_fit(
double *
a,
size_t na,
const double *
x,
const double *
y,
size_t n)
178 GSL_ERROR(
"Requested polynomial with more coefficients than data points", GSL_EINVAL);
179 }
else if (na == 0) {
180 GSL_ERROR(
"Requested a polynomial with zero coefficients", GSL_EINVAL);
181 }
else if (na == 1) {
182 *
a = gsl_stats_mean(
y, 1, n);
184 }
else if (na == 2) {
186 return gsl_fit_linear(
x, 1,
y, 1, n, &
a[0], &
a[1], &unused, &unused, &unused, &unused);
189 double X[n][na], A[n][na],
Q[na][na], QSI[na][na], C[na][na], S[na], t[n], xt[na], D[na], unused;
190 gsl_matrix_view Xview = gsl_matrix_view_array(*X, n, na);
191 gsl_matrix_view Aview = gsl_matrix_view_array(*A, n, na);
192 gsl_matrix_view Qview = gsl_matrix_view_array(*
Q, na, na);
193 gsl_matrix_view QSIview = gsl_matrix_view_array(*QSI, na, na);
194 gsl_matrix_view Cview = gsl_matrix_view_array(*C, na, na);
195 gsl_vector_view Sview = gsl_vector_view_array(S, na);
196 gsl_vector_view tview = gsl_vector_view_array(t, n);
197 gsl_vector_view xtview = gsl_vector_view_array(xt, na);
198 gsl_vector_view Dview = gsl_vector_view_array(D, na);
199 gsl_vector_const_view yview = gsl_vector_const_view_array(
y, n);
200 gsl_vector_view cview = gsl_vector_view_array(
a, na);
202 gsl_multifit_linear_workspace workspace = {
203 .A = &Aview.matrix, .Q = &Qview.matrix, .QSI = &QSIview.matrix, .S
204 = &Sview.vector, .t = &tview.vector, .xt = &xtview.vector, .D =
207 #if GSL_MAJOR_VERSION < 2
215 for (
size_t i = 0; i < n; i ++)
216 for (
size_t ia = 0; ia < na; ia ++)
217 X[i][ia] = gsl_pow_int(
x[i], ia);
219 return gsl_multifit_linear(&Xview.matrix, &yview.vector,
220 &cview.vector, &Cview.matrix, &unused, &workspace);
230#define CUBIC_SPLINE_WINDOW_SIZE 2
236 const double complex *data,
247 double complex y_max = data[-1];
248 double amp_max = cabs(y_max);
250 for (
int i = 0; i < 2; i ++)
252 double amp = cabs(data[i]);
262 for (
int i = -1; i < 1; i ++)
264 double polys[2][4], deriv[6] = {0}, roots[5];
272 for (
int j = 0; j < 2; j ++)
274 double data_part[4], deriv_part[3];
275 for (
int k = 0; k < 4; k ++)
276 data_part[k] = ((
const double *) data)[(k + i - 1) * 2 + j];
279 poly_mac(deriv, polys[j], 4, deriv_part, 3);
283 if (result != GSL_SUCCESS)
286 for (
size_t j = 0; j < nroots; j ++)
288 if (roots[j] > 0 && roots[j] < 1)
290 double complex y_new =
crect(
291 gsl_poly_eval(polys[0], 4, roots[j]),
292 gsl_poly_eval(polys[1], 4, roots[j]));
293 double amp = cabs(y_new);
296 t_max = roots[j] + i;
318 const double complex *data,
328 double t_max, amp_max, arg_max;
338 for (
int i = 0; i < 2; i ++)
340 if (amps[i + 2] > amp_max)
343 amp_max = amps[i + 2];
344 arg_max =
args[i + 2];
349 for (
int i = -1; i < 1; i ++)
351 double amp_poly[4], arg_poly[4], der[3], roots[2];
360 if (result != GSL_SUCCESS)
363 for (
size_t j = 0; j < nroots; j ++)
366 if (roots[j] < 0 || roots[j] > 1)
369 amp = gsl_poly_eval(amp_poly, 4, roots[j]);
370 arg = gsl_poly_eval(arg_poly, 4, roots[j]);
375 t_max = roots[j] + i;
404 return gsl_sf_sinc(t) * gsl_sf_sinc(t /
a);
411 double complex ret = 0;
412 for (
int i = -(
int)params->
window; i <= (
int)params->
window; i ++)
427 double complex *ymax,
428 const double complex *data,
432 GSL_ERROR(
"Window size must be >= 1", GSL_EINVAL);
435 const gsl_min_fminimizer_type *fminimizer_type = gsl_min_fminimizer_brent;
436 char fminimizer_state[fminimizer_type->size];
437 gsl_min_fminimizer fminimizer = {.type = fminimizer_type, .state = fminimizer_state};
443 result = gsl_min_fminimizer_set_with_values(&fminimizer, &func,
444 0, -cabs(data[0]), -1, -cabs(data[-1]), 1, -cabs(data[1]));
445 if (result != GSL_SUCCESS)
446 GSL_ERROR(
"failed to initialize minimizer", result);
449 result = gsl_min_fminimizer_iterate(&fminimizer);
450 if (result != GSL_SUCCESS)
451 GSL_ERROR(
"failed to perform minimizer iteration", result);
453 double t1 = gsl_min_fminimizer_x_lower(&fminimizer);
454 double t2 = gsl_min_fminimizer_x_upper(&fminimizer);
455 result = gsl_min_test_interval(t1, t2, 1e-6, 0);
456 }
while (result == GSL_CONTINUE);
458 if (result != GSL_SUCCESS)
459 GSL_ERROR(
"failed to perform minimizer convergence test", result);
461 *tmax = gsl_min_fminimizer_x_minimum(&fminimizer);
474 double complex *ymax,
475 const double complex *data,
491 double complex *ymax,
492 const double complex *data,
496 GSL_ERROR(
"Window size must be >= 1", GSL_EINVAL);
498 int result, i, nsamples = 2 * window + 1;
499 double t, t_new, amp, arg,
x[nsamples], amps[nsamples],
args[nsamples], amp_poly[3], arg_poly[2];
503 i = (amps[window - 1] > amps[window + 1]) ? -1 : 1;
505 amp = amps[window + i];
506 arg =
args[window + i];
508 for (i = 0; i < nsamples; i ++)
509 x[i] = i - (
int)window;
511 result =
poly_fit(amp_poly, 3,
x, amps, nsamples);
512 if (result != GSL_SUCCESS)
516 if (result != GSL_SUCCESS)
519 if (amp_poly[2] == 0)
520 t_new = GSL_SIGN(amp_poly[1]);
522 t_new = -0.5 * amp_poly[1] / amp_poly[2];
524 if (t_new > -1 && t_new < 1)
526 double amp_new = gsl_poly_eval(amp_poly, 3, t_new);
527 double arg_new = gsl_poly_eval(arg_poly, 2, t_new);
static int poly_real_roots(size_t *nroots, double *r, const double *a, size_t n)
#define CUBIC_SPLINE_WINDOW_SIZE
static double lanczos_cost(double t, void *params)
static double lanczos(double t, double a)
static void poly_interp(double *a, const double y[4])
static void unwrap(double *arg, size_t n)
static int poly_fit(double *a, size_t na, const double *x, const double *y, size_t n)
static void cabs_carg_unwrapped(double *amp, double *arg, const double complex *y, size_t n)
static size_t poly_strip(const double *a, size_t n)
static void poly_mac(double *y, const double *a, size_t na, const double *b, size_t nb)
static void poly_der(double *y, const double *a, size_t n)
int XLALTriggerInterpolateNearestNeighbor(double *tmax, double complex *ymax, const double complex *data, __attribute__((unused)) unsigned int window)
static double complex lanczos_interpolant(double t, const lanczos_params *params)
static double Q(double mu, double x)
#define crect(re, im)
Construct a COMPLEX16 from real and imaginary parts.
#define cpolar(r, th)
Construct a COMPLEX16 from polar modulus and argument.
int XLALTriggerInterpolateQuadraticFit(double *tmax, double complex *ymax, const double complex *data, unsigned int window)
Quadratic fit.
int XLALTriggerInterpolateCubicSplineAmpPhase(double *t, double complex *y, const double complex *data, unsigned int window)
Catmull-Rom cubic spline interpolation on amplitude phase.
int XLALTriggerInterpolateCubicSpline(double *t, double complex *y, const double complex *data, unsigned int window)
Catmull-Rom cubic spline interpolation.
int XLALTriggerInterpolateLanczos(double *tmax, double complex *ymax, const double complex *data, unsigned int window)
Lanczos interpolation.
const double complex * data