24#include <gsl/gsl_errno.h>
25#include <gsl/gsl_machine.h>
26#include <gsl/gsl_math.h>
27#include <gsl/gsl_poly.h>
28#include <gsl/gsl_randist.h>
29#include <gsl/gsl_rng.h>
30#include <gsl/gsl_sf_trig.h>
31#include <gsl/gsl_test.h>
33#include <lal/TriggerInterpolate.h>
36static double cpart(
double complex z,
int i)
38 return ((
double *)&z)[i];
44 arg = fmod(arg, 2 * M_PI);
56 return (cos(M_PI * t) - gsl_sf_sinc(t)) / t;
63 return -(sin(M_PI * t) * M_PI + 2 *
dsinc(t)) / t;
72 fdf[0] = fdf[1] = fdf[2] = 0;
75 double sinct = gsl_sf_sinc(t), sincta = gsl_sf_sinc(ta);
77 double d2sinct =
d2sinc(t), d2sincta =
d2sinc(ta) / gsl_pow_2(
a);
78 fdf[0] = sinct * sincta;
79 fdf[1] = sinct * dsincta + sincta * dsinct;
80 fdf[2] = 2 * dsinct * dsincta + sinct * d2sincta + sincta * d2sinct;
91 gsl_stream_printf(
"ERROR",
file, line, reason);
95#define TEST_WINDOW_SIZE_TOO_SMALL(FUNC, MIN_WINDOW) \
97 gsl_error_handler_t *old_handler = gsl_set_error_handler_off(); \
98 for (unsigned int window = 0; window < MIN_WINDOW; window ++) \
100 double complex y[2 * window + 1]; \
101 result = FUNC(&tmax, &ymax, &y[window], window); \
102 gsl_test(result != GSL_EINVAL, "%s window=%u returns GSL_EINVAL", #FUNC, window); \
104 gsl_set_error_handler(old_handler); \
119 double t = gsl_ran_flat(rng, -1, 1);
120 double a = -gsl_ran_gamma(rng, 2, 1);
121 double b = -2 *
a * t;
122 double c = gsl_ran_gamma(rng, 2, 1) -
a * window * (window + 2 * fabs(t));
127 *amp_max = c - 0.25 * gsl_pow_2(b) /
a;
135 poly[0] = gsl_ran_flat(rng, -M_PI, M_PI);
136 poly[1] = gsl_ran_flat(rng, -M_PI, M_PI);
142 gsl_rng *rng = gsl_rng_alloc(gsl_rng_default);
155 for (
unsigned int window = 1; window < 50; window ++)
157 unsigned int len = 2 * window + 1;
158 double complex
y[len], (*data) = &
y[window], central_datum;
161 for (
unsigned int i = 0; i < len; i ++)
162 y[i] =
crect(gsl_ran_gaussian(rng, 1), gsl_ran_gaussian(rng, 1));
165 central_datum = data[0];
166 central_datum /= cabs(central_datum);
169 double tmax_expected = gsl_ran_flat(rng, -1, 1);
173 double complex pdp[3] = {0}, qdq[3];
174 double a = 0, b = 0, c = 0, a1 = 0, b1 = 0,
c1 = 0, roots[2], fdf[3];
175 for (
unsigned int i = 1; i <= window; i ++)
179 double complex datum = data[
sign * (int)i];
181 for (
int deriv = 0; deriv < 3; deriv++)
182 pdp[deriv] += datum * fdf[deriv];
186 for (
int deriv = 0; deriv < 3; deriv ++)
187 qdq[deriv] = central_datum * fdf[deriv];
188 for (
int part = 0; part < 2; part ++)
193 c +=
cpart(pdp[0], part) *
cpart(pdp[1], part);
196 a1 += gsl_pow_2(
cpart(qdq[1], part)) +
cpart(qdq[0], part) *
cpart(qdq[2], part);
198 c1 += gsl_pow_2(
cpart(pdp[1], part)) +
cpart(pdp[0], part) *
cpart(pdp[2], part);
200 int nroots = gsl_poly_solve_quadratic(
a, b, c, &roots[0], &roots[1]);
201 for (
int iroot = 0; iroot < nroots; iroot ++)
203 double root = roots[iroot];
204 double complex ymax_expected = pdp[0] + root * qdq[0];
205 double abs_expected = cabs(ymax_expected);
206 data[0] = root * central_datum;
208 double second_deriv = a1 * gsl_pow_2(root) + b1 * root +
c1;
211 if (second_deriv >= 0)
215 if (abs_expected <= GSL_MAX_DBL(cabs(data[0]), GSL_MAX_DBL(cabs(data[-1]), cabs(data[1]))))
220 if (fabs(root) <= GSL_MAX_DBL(cabs(data[-1]), cabs(data[1])))
224 gsl_test(result,
"XLALTriggerInterpolateLanczos random signal window=%u return value", window);
225 gsl_test_abs(tmax, tmax_expected, 1e-6,
"XLALTriggerInterpolateLanczos random signal window=%u tmax", window);
226 gsl_test_abs(cabs(ymax), cabs(ymax_expected), 1e-6,
"XLALTriggerInterpolateLanczos random signal window=%u abs", window);
227 gsl_test_abs(carg(ymax), carg(ymax_expected), 1e-6,
"XLALTriggerInterpolateLanczos random signal window=%u arg", window);
232 for (
unsigned int window = 1; window < 100; window ++)
234 unsigned int len = 2 * window + 1;
235 double amp_poly[3], arg_poly[2], tmax_expected, amp_expected;
238 double arg_expected =
to_phase_angle(gsl_poly_eval(arg_poly, 2, tmax_expected));
239 double complex
y[len];
240 for (
unsigned int i = 0; i < len; i ++)
242 double x = (int)i - (
int)window;
243 double amp = gsl_poly_eval(amp_poly, 3,
x);
244 double arg = gsl_poly_eval(arg_poly, 2,
x);
249 gsl_test(result,
"XLALTriggerInterpolateQuadraticFit window=%u return value", window);
250 gsl_test_abs(tmax, tmax_expected, 1e3 * GSL_DBL_EPSILON,
"XLALTriggerInterpolateQuadraticFit quadratic signal window=%u tmax", window);
251 gsl_test_abs(cabs(ymax), amp_expected, 1e6 * GSL_DBL_EPSILON,
"XLALTriggerInterpolateQuadraticFit quadratic signal window=%u abs", window);
252 gsl_test_abs(carg(ymax), arg_expected, 1e6 * GSL_DBL_EPSILON,
"XLALTriggerInterpolateQuadraticFit quadratic signal window=%u arg", window);
257 gsl_test(result,
"XLALTriggerInterpolateCubicSplineAmpPhase quadratic signal window=%u return value", window);
258 gsl_test_abs(tmax, tmax_expected, 1e5 * GSL_DBL_EPSILON,
"XLALTriggerInterpolateCubicSplineAmpPhase quadratic signal window=%u tmax", window);
259 gsl_test_abs(cabs(ymax), amp_expected, 1e5 * GSL_DBL_EPSILON,
"XLALTriggerInterpolateCubicSplineAmpPhase quadratic signal window=%u abs", window);
260 gsl_test_abs(carg(ymax), arg_expected, 1e5 * GSL_DBL_EPSILON,
"XLALTriggerInterpolateCubicSplineAmpPhase quadratic signal window=%u arg", window);
265 for (
int run = 0; run < 100; run ++)
267 unsigned int window = 2, len = 2 * window + 1;
268 double amp_poly[3], tmax_expected, re_expected, im_expected = 0;
270 double complex
y[len];
271 for (
unsigned int i = 0; i < len; i ++)
273 double x = (int)i - (
int)window;
274 y[i] = gsl_poly_eval(amp_poly, 3,
x);
278 gsl_test(result,
"XLALTriggerInterpolateCubicSpline quadratic real part window=%u return value", window);
279 gsl_test_abs(tmax, tmax_expected, 1e6 * GSL_DBL_EPSILON,
"XLALTriggerInterpolateCubicSpline quadratic real part window=%u tmax", window);
280 gsl_test_abs(creal(ymax), re_expected, 1e6 * GSL_DBL_EPSILON,
"XLALTriggerInterpolateCubicSpline quadratic real part window=%u real", window);
281 gsl_test_abs(cimag(ymax), im_expected, 0,
"XLALTriggerInterpolateCubicSpline quadratic real part window=%u imag", window);
285 for (
unsigned int window = 1; window < 100; window ++)
287 unsigned int len = 2 * window + 1;
288 int sign = 2 * gsl_ran_bernoulli(rng, 0.5) - 1;
289 double complex
y[len];
290 double tmax_expected =
sign;
291 double real_expected = window + 1;
292 double imag_expected = 0;
293 for (
unsigned int i = 0; i < len; i ++)
295 double x = (int)i - (
int)window;
300 gsl_test(result,
"XLALTriggerInterpolateQuadraticFit linear signal window=%u return value", window);
301 gsl_test_abs(tmax, tmax_expected, 0,
"XLALTriggerInterpolateQuadraticFit linear signalwindow=%u tmax", window);
302 gsl_test_abs(creal(ymax), real_expected, 0,
"XLALTriggerInterpolateQuadraticFit linear signal window=%u real", window);
303 gsl_test_abs(cimag(ymax), imag_expected, 0,
"XLALTriggerInterpolateQuadraticFit linear signal window=%u imag", window);
308 gsl_test(result,
"XLALTriggerInterpolateCubicSpline linear signal window=%u return value", window);
309 gsl_test_abs(tmax, tmax_expected, 0,
"XLALTriggerInterpolateCubicSpline linear signal window=%u tmax", window);
310 gsl_test_abs(creal(ymax), real_expected, 0,
"XLALTriggerInterpolateCubicSpline linear signal window=%u imag", window);
311 gsl_test_abs(cimag(ymax), imag_expected, 0,
"XLALTriggerInterpolateCubicSpline linear signal window=%u imag", window);
314 gsl_test(result,
"XLALTriggerInterpolateCubicSplineAmpPhase linear signal window=%u return value", window);
315 gsl_test_abs(tmax, tmax_expected, 0,
"XLALTriggerInterpolateCubicSplineAmpPhase linear signal window=%u tmax", window);
316 gsl_test_abs(creal(ymax), real_expected, 0,
"XLALTriggerInterpolateCubicSplineAmpPhase linear signal window=%u imag", window);
317 gsl_test_abs(cimag(ymax), imag_expected, 0,
"XLALTriggerInterpolateCubicSplineAmpPhase linear signal window=%u imag", window);
322 for (
int i = 0; i < 100; i ++)
324 double complex
y =
crect(gsl_ran_gaussian(rng, 1), gsl_ran_gaussian(rng, 1));
326 gsl_test(result,
"XLALTriggerInterpolateNearestNeighbor return value");
327 gsl_test_abs(tmax, 0, 0,
"XLALTriggerInterpolateNearestNeighbor tmax");
328 gsl_test_abs(creal(ymax), creal(
y), 0,
"XLALTriggerInterpolateNearestNeighbor real part");
329 gsl_test_abs(cimag(ymax), cimag(
y), 0,
"XLALTriggerInterpolateNearestNeighbor imag part");
332 return gsl_test_summary();
int XLALTriggerInterpolateNearestNeighbor(double *tmax, double complex *ymax, const double complex *data, __attribute__((unused)) unsigned int window)
static double d2sinc(double t)
static double cpart(double complex z, int i)
static void ran_amp_poly_quadratic(gsl_rng *rng, double poly[3], double *t_max, double *amp_max, unsigned int window)
int main(__attribute__((unused)) int argc, __attribute__((unused)) char **argv)
#define TEST_WINDOW_SIZE_TOO_SMALL(FUNC, MIN_WINDOW)
static void print_gsl_error(const char *reason, const char *file, int line, __attribute__((unused)) int gsl_errno)
static double to_phase_angle(double arg)
static double dsinc(double t)
static void fdf_lanczos(double fdf[3], double t, double a)
static void ran_arg_poly_linear(gsl_rng *rng, double poly[2])
#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.