19Kernel::Logger logger(
"mathSupport");
22template <
typename InputIter>
23int solveQuadratic(
const InputIter Coef, std::pair<std::complex<double>, std::complex<double>> &OutAns)
32 const double a = (*Coef);
33 const double b = *(Coef + 1);
34 const double c = *(Coef + 2);
38 OutAns.first = std::complex<double>(0.0, 0.0);
39 OutAns.second = std::complex<double>(0.0, 0.0);
42 OutAns.first = std::complex<double>(-c / b, 0.0);
43 OutAns.second = OutAns.first;
47 const double complex_part_sq = b * b - 4 * a * c;
48 if (complex_part_sq == 0.) {
49 OutAns.first = std::complex<double>(-0.5 * b / a, 0.0);
50 OutAns.second = OutAns.first;
52 }
else if (complex_part_sq > 0.) {
53 const double complex_part = sqrt(complex_part_sq);
54 const double q = (b >= 0) ? -0.5 * (b + complex_part) : -0.5 * (b - complex_part);
55 OutAns.first = std::complex<double>(q / a, 0.0);
56 OutAns.second = std::complex<double>(c / q, 0.0);
59 const double complex_part = sqrt(-complex_part_sq);
60 std::complex<double> CQ(-0.5 * b, (b >= 0 ? -0.5 * complex_part : 0.5 * complex_part));
61 OutAns.first = CQ / a;
62 OutAns.second = c / CQ;
67template <
typename CInputIter>
68int solveCubic(
const CInputIter Coef, std::complex<double> &AnsA, std::complex<double> &AnsB,
69 std::complex<double> &AnsC)
79 using Cpair = std::complex<double>;
81 double termR, discrim;
83 std::pair<std::complex<double>, std::complex<double>> SQ;
92 if (*(Coef + 3) == 0) {
94 logger.debug() <<
"Xi == " << xi <<
'\n';
96 AnsB = (xi == 1) ? SQ.first : SQ.second;
97 AnsC = std::complex<double>(0.0, 0.0);
98 return (AnsC != AnsA) ? xi + 1 : xi;
100 const double a = (*Coef);
101 const double b = *(Coef + 1) / a;
102 const double c = *(Coef + 2) / a;
103 const double d = *(Coef + 3) / a;
105 q = (3.0 * c - (b * b)) / 9.0;
106 r = -27.0 *
d + b * (9.0 * c - 2.0 * b * b);
109 discrim = q * q * q + r * r;
115 double s = r + sqrt(discrim);
116 s = ((s < 0) ? -pow(-s, (1.0 / 3.0)) : pow(s, (1.0 / 3.0)));
117 double t = r - sqrt(discrim);
118 t = ((t < 0) ? -pow(-t, (1.0 / 3.0)) : pow(t, (1.0 / 3.0)));
119 AnsA = Cpair(-termR + s + t, 0.0);
121 termR += (s + t) / 2.0;
122 double termI = sqrt(3.0) * (-t + s) / 2;
123 AnsB = Cpair(-termR, termI);
124 AnsC = Cpair(-termR, -termI);
133 double q3 = q * q * q;
134 q3 = acos(-r / sqrt(q3));
135 r13 = -2.0 * sqrt(q);
136 AnsA = Cpair(-termR + r13 * cos(q3 / 3.0), 0.0);
137 AnsB = Cpair(-termR + r13 * cos((q3 + 2.0 * M_PI) / 3.0), 0.0);
138 AnsC = Cpair(-termR + r13 * cos((q3 - 2.0 * M_PI) / 3.0), 0.0);
145 r13 = ((r < 0) ? -pow(-r, (1.0 / 3.0)) : pow(r, (1.0 / 3.0)));
146 AnsA = Cpair(-termR + 2.0 * r13, 0.0);
147 AnsB = Cpair(-(r13 + termR), 0.0);
148 AnsC = Cpair(-(r13 + termR), 0.0);
155 std::pair<std::complex<double>, std::complex<double>> &);
156template MANTID_GEOMETRY_DLL
int solveQuadratic(
double *, std::pair<std::complex<double>, std::complex<double>> &);
157template MANTID_GEOMETRY_DLL
int solveQuadratic(
const std::vector<double>::const_iterator,
158 std::pair<std::complex<double>, std::complex<double>> &);
159template MANTID_GEOMETRY_DLL
int solveCubic(
const double *, std::complex<double> &, std::complex<double> &,
160 std::complex<double> &);
161template MANTID_GEOMETRY_DLL
int solveCubic(
double *, std::complex<double> &, std::complex<double> &,
162 std::complex<double> &);
164template MANTID_GEOMETRY_DLL
int solveCubic(
const std::vector<double>::iterator, std::complex<double> &,
165 std::complex<double> &, std::complex<double> &);
166template MANTID_GEOMETRY_DLL
int solveCubic(
const std::vector<double>::const_iterator, std::complex<double> &,
167 std::complex<double> &, std::complex<double> &);
Helper class which provides the Collimation Length for SANS instruments.
MANTID_GEOMETRY_DLL int solveCubic(InputIter, std::complex< double > &, std::complex< double > &, std::complex< double > &)
Solve a Cubic equation.
MANTID_GEOMETRY_DLL int solveQuadratic(InputIter, std::pair< std::complex< double >, std::complex< double > > &)
Solve a Quadratic equation.