26 bool solveQuadratic(
const double a,
const double b,
const double c, std::vector<double>& roots,
31 cout <<
"No solution to equation " << a <<
" x^2 + " << b <<
" x + " << c << endl
35 roots.push_back(-c / b);
37 cout <<
"Solution of " << b <<
" x + " << c <<
": " << roots[0]
38 <<
", test = " << b * roots[0] + c << endl
43 const double rho =
SQ(b) - 4. * a * c;
47 roots.push_back(sqrt(rho) / (2. * a));
48 roots.push_back(-sqrt(rho) / (2. * a));
50 const double x = -0.5 * (b +
sign(b) * sqrt(rho));
51 roots.push_back(x / a);
52 roots.push_back(c / x);
55 cout <<
"Solutions of " << a <<
" x^2 + " << b <<
" x + " << c <<
":" << endl;
56 for (
unsigned short i = 0; i < roots.size(); i++)
57 cout <<
"x" << i <<
" = " << roots[i]
58 <<
", test = " << a *
SQ(roots[i]) + b * roots[i] + c << endl;
64 cout <<
"No real solutions to " << a <<
" x^2 + " << b <<
" x + " << c << endl << endl;
69 bool solveCubic(
const double a,
const double b,
const double c,
const double d,
70 std::vector<double>& roots,
bool verbose) {
75 const double an = b / a;
76 const double bn = c / a;
77 const double cn = d / a;
79 const double Q =
SQ(an) / 9. - bn / 3.;
80 const double R =
CB(an) / 27. - an * bn / 6. + cn / 2.;
83 const double theta = acos(R / sqrt(
CB(Q))) / 3.;
85 roots.push_back(-2. * sqrt(Q) * cos(theta) - an / 3.);
86 roots.push_back(-2. * sqrt(Q) * cosXpm2PI3(theta, 1.) - an / 3.);
87 roots.push_back(-2. * sqrt(Q) * cosXpm2PI3(theta, -1.) - an / 3.);
89 const double A = -
sign(R) * cbrt(abs(R) + sqrt(
SQ(R) -
CB(Q)));
98 const double x = A + B - an / 3.;
106 cout <<
"Solutions of " << a <<
" x^3 + " << b <<
" x^2 + " << c <<
" x + " << d <<
":" 108 for (
unsigned short i = 0; i < roots.size(); i++)
109 cout <<
"x" << i <<
" = " << roots[i]
110 <<
", test = " << a *
CB(roots[i]) + b *
SQ(roots[i]) + c * roots[i] + d << endl;
117 bool solveQuartic(
const double a,
const double b,
const double c,
const double d,
const double e,
118 std::vector<double>& roots,
bool verbose) {
121 return solveCubic(b, c, d, e, roots, verbose);
123 if (!b && !c && !d && !e) {
128 }
else if (!b && !d) {
129 std::vector<double> sq_sol;
131 for (
unsigned short i = 0; i < sq_sol.size(); ++i) {
134 roots.push_back(sqrt(sq_sol[i]));
135 roots.push_back(-sqrt(sq_sol[i]));
138 const double an = b / a;
139 const double bn = c / a - (3. / 8.) *
SQ(b / a);
140 const double cn =
CB(0.5 * b / a) - 0.5 * b * c /
SQ(a) + d / a;
142 -3. *
QU(0.25 * b / a) + e / a - 0.25 * b * d /
SQ(a) + c *
SQ(b / 4.) /
CB(a);
144 std::vector<double> res;
148 for (
unsigned short i = 0; i < res.size(); ++i) {
157 cout <<
"No real solution to " << a <<
" x^4 + " << b <<
" x^3 + " << c <<
" x^2 + " 158 << d <<
" x + " << e <<
" (no positive root for the resolvent cubic)." << endl
163 const double p = sqrt(res[pChoice]);
164 solveQuadratic(p,
SQ(p), 0.5 * (p * (bn + res[pChoice]) - cn), roots, verbose);
165 solveQuadratic(p, -
SQ(p), 0.5 * (p * (bn + res[pChoice]) + cn), roots, verbose);
167 for (
unsigned short i = 0; i < roots.size(); ++i)
171 size_t nRoots = roots.size();
175 cout <<
"Solutions of " << a <<
" x^4 + " << b <<
" x^3 + " << c <<
" x^2 + " << d
176 <<
" x + " << e <<
":" << endl;
177 for (
unsigned short i = 0; i < nRoots; i++)
178 cout <<
"x" << i <<
" = " << roots[i] <<
", test = " 179 << a *
QU(roots[i]) + b *
CB(roots[i]) + c *
SQ(roots[i]) + d * roots[i] + e
183 cout <<
"No real solution to " << a <<
" x^4 + " << b <<
" x^3 + " << c <<
" x^2 + " 184 << d <<
" x + " << e << endl
192 bool solve2Quads(
const double a20,
const double a02,
const double a11,
const double a10,
193 const double a01,
const double a00,
const double b20,
const double b02,
194 const double b11,
const double b10,
const double b01,
const double b00,
195 std::vector<double>& E1, std::vector<double>& E2,
bool verbose) {
198 if (a20 == 0. && b20 == 0.) {
200 if (a02 != 0. || b02 != 0.) {
202 return solve2Quads(a02, a20, a11, a01, a10, a00, b02, b20, b11, b01, b10, b00, E2, E1,
205 return solve2QuadsDeg(a11, a10, a01, a00, b11, b10, b01, b00, E1, E2, verbose);
209 const double alpha = b20 * a02 - a20 * b02;
210 const double beta = b20 * a11 - a20 * b11;
211 const double gamma = b20 * a10 - a20 * b10;
212 const double delta = b20 * a01 - a20 * b01;
213 const double omega = b20 * a00 - a20 * b00;
215 const double a = a20 *
SQ(alpha) + a02 *
SQ(beta) - a11 * alpha * beta;
216 const double b = 2. * a20 * alpha * delta - a11 * (alpha * gamma + delta * beta) -
217 a10 * alpha * beta + 2. * a02 * beta * gamma + a01 *
SQ(beta);
218 const double c = a20 *
SQ(delta) + 2. * a20 * alpha * omega -
219 a11 * (delta * gamma + omega * beta) - a10 * (alpha * gamma + delta * beta) +
220 a02 *
SQ(gamma) + 2. * a01 * beta * gamma + a00 *
SQ(beta);
221 const double d = 2. * a20 * delta * omega - a11 * omega * gamma -
222 a10 * (delta * gamma + omega * beta) + a01 *
SQ(gamma) +
223 2. * a00 * beta * gamma;
224 const double e = a20 *
SQ(omega) - a10 * omega * gamma + a00 *
SQ(gamma);
228 for (
unsigned short i = 0; i < E2.size(); ++i) {
230 const double e2 = E2[i];
232 if (beta * e2 + gamma != 0.) {
235 const double e1 = -(alpha *
SQ(e2) + delta * e2 + omega) / (beta * e2 + gamma);
238 }
else if (alpha *
SQ(e2) + delta * e2 + omega == 0.) {
241 std::vector<double> e1;
243 if (!
solveQuadratic(a20, a11 * e2 + a10, a02 *
SQ(e2) + a01 * e2 + a00, e1, verbose)) {
247 cout <<
"Error in solve2Quads: there should be at least one solution for e1!" 260 if (i < E2.size() - 1) {
262 if (e2 != E2[i + 1]) {
263 cout <<
"Error in solve2Quads: if there are two solutions for e1, e2 " 264 "should be degenerate!" 277 cout <<
"Error in solve2Quads: if there are two solutions for e1, e2 should be " 288 E2.erase(E2.begin() + i);
296 bool solve2QuadsDeg(
const double a11,
const double a10,
const double a01,
const double a00,
297 const double b11,
const double b10,
const double b01,
const double b00,
298 vector<double>& E1, vector<double>& E2,
bool verbose) {
300 if (a11 == 0. && b11 == 0.)
301 return solve2Linear(a10, a01, a00, b10, b01, b00, E1, E2, verbose);
304 a01 * (b11 * a10 - a11 * b10) - a01 * (b11 * a01 - a11 * b01) +
305 a11 * (b11 * a00 - a11 * b00),
306 a01 * (b11 * a00 - a11 * b00), E1, verbose);
310 cout <<
"No solution to the system:" << endl;
311 cout <<
" " << a11 <<
"*E1*E2 + " << a10 <<
"*E1 + " << a01 <<
"*E2 + " << a00 <<
" = 0" 313 cout <<
" " << b11 <<
"*E1*E2 + " << b10 <<
"*E1 + " << b01 <<
"*E2 + " << b00 <<
" = 0" 320 for (
unsigned short i = 0; i < E1.size(); ++i) {
322 double denom = a11 * E1[i] + a01;
325 E2.push_back(-(a10 * E1[i] + a00) / denom);
328 denom = b11 * a01 - a11 * b01;
330 E2.push_back(-((b11 * a10 - a11 * b10) * E1[i] + b11 * a00 - a11 * b00) / denom);
332 denom = b11 * E1[i] + b01;
334 E2.push_back(-(b10 * E1[i] + b00) / denom);
336 E1.erase(E1.begin() + i);
344 cout <<
"Solutions to the system:" << endl;
345 cout <<
" " << a11 <<
"*E1*E2 + " << a10 <<
"*E1 + " << a01 <<
"*E2 + " << a00 <<
" = 0" 347 cout <<
" " << b11 <<
"*E1*E2 + " << b10 <<
"*E1 + " << b01 <<
"*E2 + " << b00 <<
" = 0" 349 for (
unsigned short i = 0; i < E1.size(); ++i)
350 cout <<
" E1 = " << E1[i] <<
", E2 = " << E2[i] << endl;
357 bool solve2Linear(
const double a10,
const double a01,
const double a00,
const double b10,
358 const double b01,
const double b00, std::vector<double>& E1,
359 std::vector<double>& E2,
bool verbose) {
361 const double det = a10 * b01 - b10 * a01;
364 if (a00 != 0. || b00 != 0.) {
366 cout <<
"No solution to the system:" << endl;
367 cout <<
" " << a10 <<
"*E1 + " << a01 <<
"*E2 + " << a00 <<
" = 0" << endl;
368 cout <<
" " << b10 <<
"*E1 + " << b01 <<
"*E2 + " << b00 <<
" = 0" << endl;
373 cout <<
"Error in solve2Linear: indeterminate system:" << endl;
374 cout <<
" " << a10 <<
"*E1 + " << a01 <<
"*E2 + " << a00 <<
" = 0" << endl;
375 cout <<
" " << b10 <<
"*E1 + " << b01 <<
"*E2 + " << b00 <<
" = 0" << endl;
381 const double e2 = (b10 * a00 - a10 * b00) / det;
385 e1 = -(b00 + b01 * e2) / b10;
387 e1 = -(a00 + a01 * e2) / a10;
391 cout <<
"Solution to the system:" << endl;
392 cout <<
" " << a10 <<
"*E1 + " << a01 <<
"*E2 + " << a00 <<
" = 0" << endl;
393 cout <<
" " << b10 <<
"*E1 + " << b01 <<
"*E2 + " << b00 <<
" = 0" << endl;
394 cout <<
" E1 = " << e1 <<
", E2 = " << e2 << endl << endl;
400 double BreitWigner(
const double s,
const double m,
const double g) {
402 return k / (std::pow(s - m * m, 2.) + std::pow(m * g, 2.));
410 static const double epsilon = std::numeric_limits<float>::epsilon() * 100;
411 static const double margin = 1.0;
412 static const double scale = 1.0;
414 bool relativeOK = std::fabs(value - expected) < epsilon * (scale + (std::max)(std::fabs(value), std::fabs(expected)));
418 return std::fabs(value - expected) < margin;
bool solveQuartic(const double a, const double b, const double c, const double d, const double e, std::vector< double > &roots, bool verbose=false)
Finds the real solutions to .
bool ApproxComparison(double value, double expected)
Compare two doubles and return true if they are approximatively equal.
bool solveQuadratic(const double a, const double b, const double c, std::vector< double > &roots, bool verbose=false)
Finds the real solutions to .
T sign(const T &x)
Sign function.
bool solve2Linear(const double a10, const double a01, const double a00, const double b10, const double b01, const double b00, std::vector< double > &E1, std::vector< double > &E2, bool verbose=false)
Solve a system of two linear equations.
double BreitWigner(const double s, const double m, const double g)
A relativist Breit-Wigner distribution.
bool solve2QuadsDeg(const double a11, const double a10, const double a01, const double a00, const double b11, const double b10, const double b01, const double b00, std::vector< double > &E1, std::vector< double > &E2, bool verbose=false)
Solve a system of two degenerated quadratic equations.
bool solve2Quads(const double a20, const double a02, const double a11, const double a10, const double a01, const double a00, const double b20, const double b02, const double b11, const double b10, const double b01, const double b00, std::vector< double > &E1, std::vector< double > &E2, bool verbose=false)
Solve a system of two quadratic equations.
bool solveCubic(const double a, const double b, const double c, const double d, std::vector< double > &roots, bool verbose=false)
Finds the real solutions to .