00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <math.h>
00024 #include <gsl/gsl_math.h>
00025 #include <gsl/gsl_complex.h>
00026 #include <gsl/gsl_poly.h>
00027
00028 #define SWAP(a,b) do { double tmp = b ; b = a ; a = tmp ; } while(0)
00029
00030 int
00031 gsl_poly_complex_solve_cubic (double a, double b, double c,
00032 gsl_complex *z0, gsl_complex *z1,
00033 gsl_complex *z2)
00034 {
00035 double q = (a * a - 3 * b);
00036 double r = (2 * a * a * a - 9 * a * b + 27 * c);
00037
00038 double Q = q / 9;
00039 double R = r / 54;
00040
00041 double Q3 = Q * Q * Q;
00042 double R2 = R * R;
00043
00044
00045
00046
00047 if (R == 0 && Q == 0)
00048 {
00049 GSL_REAL (*z0) = -a / 3;
00050 GSL_IMAG (*z0) = 0;
00051 GSL_REAL (*z1) = -a / 3;
00052 GSL_IMAG (*z1) = 0;
00053 GSL_REAL (*z2) = -a / 3;
00054 GSL_IMAG (*z2) = 0;
00055 return 3;
00056 }
00057 else if (R2 == Q3)
00058 {
00059
00060
00061
00062
00063
00064
00065
00066 double sqrtQ = sqrt (Q);
00067
00068 if (R > 0)
00069 {
00070 GSL_REAL (*z0) = -2 * sqrtQ - a / 3;
00071 GSL_IMAG (*z0) = 0;
00072 GSL_REAL (*z1) = sqrtQ - a / 3;
00073 GSL_IMAG (*z1) = 0;
00074 GSL_REAL (*z2) = sqrtQ - a / 3;
00075 GSL_IMAG (*z2) = 0;
00076 }
00077 else
00078 {
00079 GSL_REAL (*z0) = -sqrtQ - a / 3;
00080 GSL_IMAG (*z0) = 0;
00081 GSL_REAL (*z1) = -sqrtQ - a / 3;
00082 GSL_IMAG (*z1) = 0;
00083 GSL_REAL (*z2) = 2 * sqrtQ - a / 3;
00084 GSL_IMAG (*z2) = 0;
00085 }
00086 return 3;
00087 }
00088 else if (R2 < Q3)
00089 {
00090 double sqrtQ = sqrt (Q);
00091 double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ;
00092 double ctheta = R / sqrtQ3;
00093 double theta = 0;
00094 if ( ctheta <= -1.0)
00095 theta = M_PI;
00096 else if ( ctheta < 1.0)
00097 theta = acos (R / sqrtQ3);
00098
00099 double norm = -2 * sqrtQ;
00100 double r0 = norm * cos (theta / 3) - a / 3;
00101 double r1 = norm * cos ((theta + 2.0 * M_PI) / 3) - a / 3;
00102 double r2 = norm * cos ((theta - 2.0 * M_PI) / 3) - a / 3;
00103
00104
00105
00106 if (r0 > r1)
00107 SWAP (r0, r1);
00108
00109 if (r1 > r2)
00110 {
00111 SWAP (r1, r2);
00112
00113 if (r0 > r1)
00114 SWAP (r0, r1);
00115 }
00116
00117 GSL_REAL (*z0) = r0;
00118 GSL_IMAG (*z0) = 0;
00119
00120 GSL_REAL (*z1) = r1;
00121 GSL_IMAG (*z1) = 0;
00122
00123 GSL_REAL (*z2) = r2;
00124 GSL_IMAG (*z2) = 0;
00125
00126 return 3;
00127 }
00128 else
00129 {
00130 double sgnR = (R >= 0 ? 1 : -1);
00131 double A = -sgnR * pow (fabs (R) + sqrt (R2 - Q3), 1.0 / 3.0);
00132 double B = Q / A;
00133
00134 if (A + B < 0)
00135 {
00136 GSL_REAL (*z0) = A + B - a / 3;
00137 GSL_IMAG (*z0) = 0;
00138
00139 GSL_REAL (*z1) = -0.5 * (A + B) - a / 3;
00140 GSL_IMAG (*z1) = -(sqrt (3.0) / 2.0) * fabs(A - B);
00141
00142 GSL_REAL (*z2) = -0.5 * (A + B) - a / 3;
00143 GSL_IMAG (*z2) = (sqrt (3.0) / 2.0) * fabs(A - B);
00144 }
00145 else
00146 {
00147 GSL_REAL (*z0) = -0.5 * (A + B) - a / 3;
00148 GSL_IMAG (*z0) = -(sqrt (3.0) / 2.0) * fabs(A - B);
00149
00150 GSL_REAL (*z1) = -0.5 * (A + B) - a / 3;
00151 GSL_IMAG (*z1) = (sqrt (3.0) / 2.0) * fabs(A - B);
00152
00153 GSL_REAL (*z2) = A + B - a / 3;
00154 GSL_IMAG (*z2) = 0;
00155 }
00156
00157 return 3;
00158 }
00159 }