solveQuartic.h
Go to the documentation of this file.00001
00016 #ifndef DLR_NUMERIC_SOLVEQUARTIC_H
00017 #define DLR_NUMERIC_SOLVEQUARTIC_H
00018
00019 #include <complex>
00020
00021 namespace dlr {
00022
00023 namespace numeric {
00024
00053 template <class Type>
00054 void
00055 solveQuartic(Type c0, Type c1, Type c2, Type c3,
00056 std::complex<Type>& root0, std::complex<Type>& root1,
00057 std::complex<Type>& root2, std::complex<Type>& root3);
00058
00059
00060 }
00061
00062 }
00063
00064
00065
00066
00067 #include <cmath>
00068 #include <dlrCommon/constants.h>
00069 #include <dlrNumeric/solveCubic.h>
00070 #include <dlrNumeric/solveQuadratic.h>
00071
00072
00073 #include <iostream>
00074
00075 namespace dlr {
00076
00077 namespace numeric {
00078
00079
00080
00081 template <class Type>
00082 void
00083 solveQuartic(Type c0, Type c1, Type c2, Type c3,
00084 std::complex<Type>& root0, std::complex<Type>& root1,
00085 std::complex<Type>& root2, std::complex<Type>& root3)
00086 {
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 Type c0Squared = c0 * c0;
00102 Type c0Cubed = c0Squared * c0;
00103 Type minus3C0Squared = Type(-3.0) * c0Squared;
00104
00105 Type alpha = (minus3C0Squared / Type(8.0)) + c1;
00106 Type beta = (c0Cubed / Type(8.0)) - ((c0 * c1) / Type(2.0)) + c2;
00107 Type gamma = (((minus3C0Squared * c0Squared) / Type(256.0))
00108 + ((c0Squared * c1) / Type(16.0)) - ((c0 * c2) / Type(4.0))
00109 + c3);
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 Type k0 = Type(2.0) * alpha;
00146 Type k1 = alpha * alpha - Type(4.0) * gamma;
00147 Type k2 = -(beta * beta);
00148 std::complex<Type> r0;
00149 std::complex<Type> r1;
00150 std::complex<Type> r2;
00151 solveCubic(k0, k1, k2, r0, r1, r2);
00152
00153
00154 Type mag2R0 = r0.real() * r0.real();
00155 Type mag2R1 = r1.real() * r1.real() + r1.imag() * r1.imag();
00156 Type mag2R2 = r2.real() * r2.real() + r2.imag() * r2.imag();
00157 if(mag2R1 > mag2R0) {
00158 std::swap(r1, r0);
00159 std::swap(mag2R1, mag2R0);
00160 }
00161 if(mag2R2 > mag2R0) {
00162 std::swap(r2, r0);
00163 std::swap(mag2R2, mag2R0);
00164 }
00165
00166
00167 std::complex<Type> pp = std::sqrt(r0);
00168
00169
00170
00171
00172
00173 std::complex<Type> alphaPlusPpSquared = alpha + pp * pp;
00174 std::complex<Type> betaOverPp =
00175 mag2R0 ? (beta / pp) : std::complex<Type>(Type(0.0), Type(0.0));
00176 std::complex<Type> ss = (alphaPlusPpSquared + betaOverPp) / Type(2.0);
00177 std::complex<Type> qq = (alphaPlusPpSquared - betaOverPp) / Type(2.0);
00178
00179
00180
00181
00182
00183
00184
00185 solveQuadratic(pp, qq, r0, r1);
00186 root0 = r0 - c0 / Type(4.0);
00187 root1 = r1 - c0 / Type(4.0);
00188
00189 solveQuadratic(-pp, ss, r0, r1);
00190 root2 = r0 - c0 / Type(4.0);
00191 root3 = r1 - c0 / Type(4.0);
00192 }
00193
00194 }
00195
00196 }
00197
00198 #endif