libpappsomspp
Library for mass spectrometry
Loading...
Searching...
No Matches
cardano.cpp
Go to the documentation of this file.
1/**
2 * \file pappsomspp/vendors/tims/mzcalibration/cardano.cpp
3 * \date 17/12/2022
4 * \brief cubic solver adapted from
5 * https://www.codeproject.com/articles/798474/to-solve-a-cubic-equation
6 thanks
7 * to "Sergey Bochkanov" <sergey.bochkanov@alglib.net> for his advise
8 */
9
10/*******************************************************************************
11 * Copyright (c) 2022 Olivier Langella <Olivier.Langella@u-psud.fr>.
12 *
13 * This file is part of the PAPPSOms++ library.
14 *
15 * PAPPSOms++ is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation, either version 3 of the License, or
18 * (at your option) any later version.
19 *
20 * PAPPSOms++ is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with PAPPSOms++. If not, see <http://www.gnu.org/licenses/>.
27 *
28 ******************************************************************************/
29
30#include "cardano.h"
31
32
33#include <cmath>
34#include <QDebug>
35
36
37const double BUFFER_SQRT3{std::sqrt(3.0)};
38const double BUFFER_inv27{1.0 / 27.0};
39const double BUFFER_pow11{std::pow(10.0, -11.0)};
40
41void
42cubic_solver(InHousePolynomialSolverResult &res, double a1, double b, double c, double d)
43{
44
45 /**
46 * @todo Cardaono cubic solver
47 *
48 * adapted in c++ from
49 * https://www.codeproject.com/articles/798474/to-solve-a-cubic-equation
50 thanks
51 * to "Sergey Bochkanov" <sergey.bochkanov@alglib.net> for his advise
52 *
53 * Cubic Equation
54 https://github.com/harveytriana/CubicEquation
55 Quartic Equation
56 https://github.com/harveytriana/QuarticEcuation
57 */
58 double a, p, q, u, v;
59 double r, alpha;
60 a = b / a1;
61 b = c / a1;
62 c = d / a1;
63
64 double aover3(a / 3.0);
65 p = -(a * aover3) + b;
66 q = (2.0 * BUFFER_inv27 * a * a * a) - (b * aover3) + c;
67 d = q * q / 4.0 + p * p * p * BUFFER_inv27;
68 if(std::abs(d) < BUFFER_pow11)
69 d = 0;
70 // 3 cases D > 0, D == 0 and D < 0
71 if(d > 1e-20)
72 {
73 double dsqrt = std::sqrt(d);
74 u = std::cbrt(-q / 2.0 + dsqrt);
75 v = std::cbrt(-q / 2.0 - dsqrt);
76 res.x1 = u + v - aover3;
77 /*
78 res.x2.real(-(u + v) / 2.0 - aover3);
79 res.x2.imag(BUFFER_SQRT3 / 2.0 * (u - v));
80 res.x3.real(res.x2.real());
81 res.x3.imag(-res.x2.imag());
82 */
84 }
85 if(std::abs(d) <= 1e-20)
86 {
87 u = std::cbrt(-q / 2.0);
88 v = u;
89 res.x1 = u + v - aover3;
90 // res.x2.real(-(u + v) / 2.0 - aover3);
91 res.type = CardanoResultCase::zerod;
92 }
93 if(d < -1e-20)
94 {
95 r = std::cbrt(std::sqrt(-p * p * p * BUFFER_inv27));
96 alpha = std::atan(std::sqrt(-d) / -q * 2.0);
97 if(q > 0) // if q > 0 the angle becomes 2 * PI - alpha
98 alpha = 2.0 * M_PI - alpha;
99
100 res.x1 = r * (std::cos((6.0 * M_PI - alpha) / 3.0) + std::cos(alpha / 3.0)) - aover3;
101 /*
102 res.x2.real(r * (std::cos((2.0 * M_PI + alpha) / 3.0) +
103 std::cos((4.0 * M_PI - alpha) / 3.0)) -
104 aover3);
105 res.x3.real(r * (std::cos((4.0 * M_PI + alpha) / 3.0) +
106 std::cos((2.0 * M_PI - alpha) / 3.0)) -
107 aover3);
108 */
110 }
111}
112
113
115inHousePolynomialSolve(const std::vector<double> &polynome)
116{
119 std::size_t polynome_size = polynome.size();
120
121 double a, b, c, delta;
122
123 switch(polynome_size)
124 {
125 case 0:
126 break;
127 case 1:
128 break;
129 case 2: // linear// equation ax + b = 0
130 a = polynome[1];
131 b = polynome[0];
132 if(a != 0)
133 {
134 res.x1 = -b / a;
135 res.type = CardanoResultCase::line;
136 }
137 break;
138 case 3:
139 // quadratic equation ax**2 + bx + c = 0
140 a = polynome[2];
141 if(a == 0)
142 return res;
143 b = polynome[1];
144 c = polynome[0];
145
146 if(a == 0)
147 return res;
148 // calculate the discriminant
149 delta = (b * b) - (a * c * 4);
150 // qDebug() << delta;
151 if(delta < 0)
152 {
153 }
154 else if(std::abs(delta) <= 1e-20)
155 {
156 res.x1 = -b / (a * 2);
157 // qDebug() << x1.real() << " " << x2.real();
159 }
160 else
161 {
162 // find two solutions
163 delta = std::sqrt(delta);
164 res.x1 = (-b + delta) / (a * 2);
165 res.x2 = (-b - delta) / (a * 2);
166
167 // qDebug() << x1.real() << " " << x2.real();
169 }
170 break;
171 case 4:
172 cubic_solver(res, polynome[3], polynome[2], polynome[1], polynome[0]);
173 }
174 return res;
175}
const double BUFFER_SQRT3
Definition cardano.cpp:37
void cubic_solver(InHousePolynomialSolverResult &res, double a1, double b, double c, double d)
Definition cardano.cpp:42
const double BUFFER_inv27
Definition cardano.cpp:38
const double BUFFER_pow11
Definition cardano.cpp:39
InHousePolynomialSolverResult inHousePolynomialSolve(const std::vector< double > &polynome)
Definition cardano.cpp:115