8 #define SINCOS __sincos 13 #ifdef ENABLE_VECTORIZE 14 #include "vectormath_trig.h" 19 #define GATHER_REAL gather4d<0,2,4,6> 20 #define GATHER_IM gather4d<1,3,5,7> 21 static VEC INDEX (0,1,2,3);
26 #define GATHER_REAL gather2d<0,2> 27 #define GATHER_IM gather2d<1,3> 28 static VEC INDEX (0,1);
34 static unsigned factorial_table[] =
52 void extirpolate(
double y,
int n,
double *yys,
double x,
int extirpolation_factor)
56 #if ( __clang__major__ >3 || (__clang_major__==3 && __clang_minor__ >=6) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__GNUC__ > 4)) 57 double * ys = (
double*) __builtin_assume_aligned(yys, 32);
59 double * ys = (
double*) yys;
64 extirpolation_factor = std::max(0,extirpolation_factor);
65 extirpolation_factor = std::min(
sizeof(factorial_table)/
sizeof(
unsigned) - 1,
size_t(extirpolation_factor));
68 if (__builtin_expect(x == ix,0)) ys[ix-1] += y;
71 int ilo = std::min( std::max(
int(x - 0.5 * extirpolation_factor),0),
int(n-extirpolation_factor));
72 int ihi = ilo +extirpolation_factor ;
74 double fac = x - ilo -1;
77 for (
int j = ilo+1; j < ihi; j++)
82 int nden = factorial_table[extirpolation_factor];
83 ys[ihi-1] += y * fac / (nden * (x- ihi));
85 for (
int j = ihi - 1; j > ilo; j--)
87 nden = (nden / (j - ilo)) * (j -ihi);
88 ys[j-1] += y * fac / (nden * (x-j));
96 static TGraph * _lombScarglePeriodogram(
int n,
double dt,
const double * __restrict x,
const double * __restrict y,
double oversample_factor = 4 ,
97 double high_factor = 2, TGraph * replaceme = 0,
int extirpolation_factor = 4)
106 __attribute((__optimize__(
"fast-math",
"tree-vectorize")));
109 TGraph * _lombScarglePeriodogram(
int n,
double dt,
const double * __restrict x,
const double * __restrict y ,
double oversample_factor,
double high_factor, TGraph * out,
int extirpolation_factor)
113 int nout = n * oversample_factor * high_factor/2;
118 if (out->GetN() != nout) out->Set(nout);
122 out =
new TGraph(nout);
125 int nfreq = n *oversample_factor * high_factor * extirpolation_factor;
126 int nwork = 2 * nfreq;
131 for (
int i = 0; i < n; i++)
144 memset(wk1,0,
sizeof(wk1));
145 memset(wk2,0,
sizeof(wk2));
147 dt = dt ? dt : (x[n-1] - x[0]) / n;
148 double range = n * dt;
151 double scale_factor = 2 * nfreq / oversample_factor / range;
152 for (
int i = 0; i < n; i++)
154 double xx1 = fmod( (x[i] - x[0]) * scale_factor, 2 * nfreq);
155 double xx2 = fmod( 2 * (xx1++) , 2 * nfreq)+1;
157 extirpolate(y[i] - mean, nwork,wk1, xx1, extirpolation_factor);
158 extirpolate(1., nwork,wk2, xx2, extirpolation_factor);
167 double df = 1./(range * oversample_factor);
168 double norm_factor = 4. / n;
170 #ifdef ENABLE_VECTORIZE 171 int leftover = nout % VEC_N;
172 int nit = nout / VEC_N + (leftover? 1: 0);
174 for (
int i = 0; i < nit; i++)
176 VEC fft2_re= GATHER_REAL((
double*) &fft2[i*VEC_N+1]);
177 VEC fft2_im = GATHER_IM((
double*) &fft2[i*VEC_N+1]);
178 VEC fft1_re= GATHER_REAL((
double*) &fft1[i*VEC_N+1]);
179 VEC fft1_im = GATHER_IM((
double*) &fft1[i*VEC_N+1]);
181 VEC invhypo = 1./sqrt((fft2_re* fft2_re+ fft2_im * fft2_im));
183 VEC half_cos2wt = 0.5 * fft2_re * invhypo;
184 VEC half_sin2wt = 0.5 * fft2_im * invhypo;
186 VEC coswt = sqrt(0.5 + half_cos2wt);
187 VEC sinwt = sign_combine(sqrt(0.5 - half_cos2wt), half_sin2wt);
189 VEC density = 0.5 * n + half_cos2wt * fft2_re + half_sin2wt * fft2_im;
190 VEC costerm = square( coswt * fft1_re + sinwt * fft1_im) / density;
191 VEC sinterm = square( coswt * fft1_re - sinwt * fft1_im) / (n -density);
194 VEC index(i * VEC_N);
197 VEC ans_x = (index + 1) * df;
198 VEC ans_y = (costerm + sinterm)*norm_factor;
199 if (i < nit-1 || leftover == 0)
201 ans_x.store(out->GetX() +i * VEC_N);
202 ans_y.store(out->GetY()+ i * VEC_N);
206 ans_x.store_partial(leftover,out->GetX() +i * VEC_N);
207 ans_y.store_partial(leftover,out->GetY()+ i * VEC_N);
213 for (
int j = 0; j < nout; j++)
215 double hypo = fft2[j+1].getAbs();
216 double half_cos2wt = 0.5 * fft2[j+1].
re / hypo;
217 double half_sin2wt = 0.5 * fft2[j+1].
im / hypo;
218 double coswt = sqrt(0.5 + half_cos2wt);
219 double sinwt = TMath::Sign(sqrt(0.5 - half_cos2wt), half_sin2wt);
221 double density = 0.5 * n + half_cos2wt * fft2[j+1].
re + half_sin2wt * fft2[j+1].
im;
223 double costerm = coswt * fft1[j+1].
re + sinwt * fft1[j+1].
im;
227 double sinterm = coswt * fft1[j+1].
re - sinwt * fft1[j+1].
im;
229 sinterm /= (n-density);
231 out->GetX()[j] = (j+1) * df;
232 out->GetY()[j] = (costerm + sinterm) * norm_factor;
242 double high_factor, TGraph * out,
int extirpolation_factor)
245 return _lombScarglePeriodogram(n,dt, x,y, oversample_factor, high_factor,out, extirpolation_factor);
251 double high_factor, TGraph * out,
int extirpolation_factor)
254 return _lombScarglePeriodogram(g->GetN(),dt, g->GetX(), g->GetY(), oversample_factor, high_factor,out, extirpolation_factor);
261 double window_vals[segment_size];
262 window->fill(segment_size, window_vals);
264 double window_weight = 0;
265 for (
int i = 0; i < segment_size; i++) window_weight += window_vals[i] * window_vals[i] / segment_size;
271 TGraph * power = gout ? gout :
new TGraph(segment_size/2+1);
275 power->Set(segment_size/2+1);
276 memset(power->GetY(),0, power->GetN() *
sizeof(double));
279 double df = 1./(segment_size * (gin->GetX()[1] - gin->GetX()[0]));
280 for (
int i = 0; i < power->GetN(); i++)
282 power->GetX()[i] = df*i;
288 while (truncate_extra ? index + segment_size < gin->GetN() : index < gin->GetN())
291 for (
int i = 0; i < segment_size; i++)
293 y[i] = i + index < gin->GetN() ? window_vals[i] * gin->GetY()[i + index] : 0;
299 power->GetY()[0] += fft[0].getAbsSq()/segment_size;
300 for (
int j = 1; j < segment_size/2; j++)
302 power->GetY()[j] += fft[j].getAbsSq() *2 / segment_size;
304 power->GetY()[segment_size/2] += fft[segment_size/2].getAbsSq() / segment_size;
308 index += (1.-overlap_fraction) * segment_size;
309 if (index + segment_size >= gin->GetN())
311 nsegs += double(gin->GetN() -index) / segment_size;
319 for (
int i = 0; i <= segment_size/2; i++) power->GetY()[i] /= nsegs * window_weight;
329 if (!answer) answer =
new double[nfreqs];
331 for (
int ifreq = 0; ifreq < nfreqs; ifreq++)
336 double two_w = freqs[ifreq] * 2 * TMath::Pi();
338 for (
int i =0; i < N; i++)
341 SINCOS(x[i] * two_w, &s,&c);
349 double tau = atan2(sin2wt, cos2wt) / two_w;
359 for (
int i = 0; i < N; i++)
361 double yy = y[i] - mean;
365 SINCOS(two_w * (x[i] - tau), &s,&c);
374 answer[ifreq] = ys*ys / s2 + yc*yc/c2;
struct __attribute__((packed))
Debugging use only TURF scaler data.
double im
The imaginary part.
This is a wrapper class for a complex number.