GooFit  v2.1.3
ComplexUtils.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <goofit/Error.h>
5 #include <vector>
6 
7 namespace GooFit {
8 
10 template <typename T>
11 std::vector<T> flatten(const std::vector<thrust::complex<T>> &input) {
12  std::vector<T> output;
13  for(auto val : input) {
14  output.push_back(val.real());
15  output.push_back(val.imag());
16  }
17  return output;
18 }
19 
20 std::vector<fpcomplex> complex_derivative(const std::vector<fptype> &x, const std::vector<fpcomplex> &y) {
21  if(x.size() != y.size()) // Must be a valid pointer
22  throw GeneralError("x and y must have the same diminsions!");
23 
24  int i, k;
25  unsigned int n = x.size();
26  std::vector<fpcomplex> u(n);
27  std::vector<fpcomplex> y2(n);
28 
29  fptype sig, p, qn, un;
30  fpcomplex yp1 = 2. * (y[1] - y[0]) / (x[1] - x[0]);
31  fpcomplex ypn = 2. * (y[n - 1] - y[n - 2]) / (x[n - 1] - x[n - 2]);
32 
33  /* The lower boundary condition is set either to be "natural" or else to have specified first derivative*/
34  if(yp1.real() > 0.99e30) {
35  y2[0].real(0.);
36  u[0].real(0.);
37  } else {
38  y2[0].real(-0.5);
39  u[0].real(3.0 / (x[1] - x[0]) * ((y[1].real() - y[0].real()) / (x[1] - x[0]) - yp1.real()));
40  }
41  if(yp1.imag() > 0.99e30) {
42  y2[0].imag(0.);
43  u[0].imag(0.);
44  } else {
45  y2[0].imag(-0.5);
46  u[0].imag(3.0 / (x[1] - x[0]) * ((y[1].imag() - y[0].imag()) / (x[1] - x[0]) - yp1.imag()));
47  }
48 
49  /* This is the decomposition loop of the tridiagonal algorithm. y2 and u are used for temporary storage of the
50  * decomposed factors*/
51 
52  for(i = 1; i < n - 1; i++) {
53  sig = (x[i] - x[i - 1]) / (x[i + 1] - x[i - 1]);
54  p = sig * y2[i - 1].real() + 2.0;
55  y2[i].real((sig - 1.0) / p);
56  u[i].real((y[i + 1].real() - y[i].real()) / (x[i + 1] - x[i])
57  - (y[i].real() - y[i - 1].real()) / (x[i] - x[i - 1]));
58  u[i].real((6.0 * u[i].real() / (x[i + 1] - x[i - 1]) - sig * u[i - 1].real()) / p);
59  p = sig * y2[i - 1].imag() + 2.0;
60  y2[i].imag((sig - 1.0) / p);
61  u[i].imag((y[i + 1].imag() - y[i].imag()) / (x[i + 1] - x[i])
62  - (y[i].imag() - y[i - 1].imag()) / (x[i] - x[i - 1]));
63  u[i].imag((6.0 * u[i].imag() / (x[i + 1] - x[i - 1]) - sig * u[i - 1].imag()) / p);
64  }
65 
66  /* The upper boundary condition is set either to be "natural" or else to have specified first derivative*/
67 
68  if(ypn.real() > 0.99e30) {
69  qn = 0.;
70  un = 0.;
71  } else {
72  qn = 0.5;
73  un = (3.0 / (x[n - 1] - x[n - 2])) * (ypn.real() - (y[n - 1].real() - y[n - 2].real()) / (x[n - 1] - x[n - 2]));
74  }
75  y2[n - 1].real((un - qn * u[n - 2].real()) / (qn * y2[n - 2].real() + 1.0));
76  if(ypn.imag() > 0.99e30) {
77  qn = 0.;
78  un = 0.;
79  } else {
80  qn = 0.5;
81  un = (3.0 / (x[n - 1] - x[n - 2])) * (ypn.imag() - (y[n - 1].imag() - y[n - 2].imag()) / (x[n - 1] - x[n - 2]));
82  }
83  y2[n - 1].imag((un - qn * u[n - 2].imag()) / (qn * y2[n - 2].imag() + 1.0));
84 
85  /* This is the backsubstitution loop of the tridiagonal algorithm */
86 
87  for(k = n - 2; k >= 0; k--) {
88  y2[k].real(y2[k].real() * y2[k + 1].real() + u[k].real());
89  y2[k].imag(y2[k].imag() * y2[k + 1].imag() + u[k].imag());
90  }
91 
92  return y2;
93 }
94 
95 } // namespace GooFit
Thrown when a general error is encountered.
Definition: Error.h:10
double fptype
std::vector< fpcomplex > complex_derivative(const std::vector< fptype > &x, const std::vector< fpcomplex > &y)
Definition: ComplexUtils.h:20
std::vector< T > flatten(const std::vector< thrust::complex< T >> &input)
Flatten a complex array into a standard one (1r, 1i, 2r, 2i, ...)
Definition: ComplexUtils.h:11
thrust::complex< fptype > fpcomplex
Definition: Complex.h:8