int QuarticEquation::Solve(double *const roots) const
{
  double r1, r2, r3, r4;
  int nr12, nr34;

  double a3 = d3/d4;
  double a2 = d2/d4;
  double a1 = d1/d4;
  double a0 = d0/d4;

  double au2 = -a2;
  double au1 = (a1*a3 - 4.0*a0) ;
  double au0 = 4.0*a0*a2 - a1*a1 - a0*a3*a3;

  double x1, x2, x3;
  int nr;
  solve_cubic_equation(1.0, au2, au1, au0, x1, x2, x3, nr);

  double u1;
  if (nr==1) {
    u1 = x1;
  }
  else {
    u1 = (x1>x3) ? x1 : x3;
  }

  double R2 = 0.25*a3*a3 + u1 - a2;
  double R = (R2>0.0) ? sqrt(R2) : 0.0;

  double D2, E2;
  if (R != 0.0) {
    double foo1 = 0.75*a3*a3 - R2 - 2.0*a2;
    double foo2 = 0.25*(4.0*a3*a2 - 8.0*a1 - a3*a3*a3) / R;
    D2 = foo1 + foo2;
    E2 = foo1 - foo2;
  }
  else {
    double foo1 = 0.75*a3*a3 - 2.0*a2;
    double foo2 = 2.0 * sqrt(u1*u1 - 4.0*a0);
    D2 = foo1 + foo2;
    E2 = foo1 - foo2;
  }

  if (D2 >= 0.0) {
    double D = sqrt(D2);
    r1 = -0.25*a3 + 0.5*R - 0.5*D;
    r2 = -0.25*a3 + 0.5*R + 0.5*D;
    nr12 = 2;
  }
  else {
    r1 = r2 = -0.25*a3 + 0.5*R;
    nr12 = 0;
  }

  if (E2 >= 0.0) {
    double E = sqrt(E2);
    r3 = -0.25*a3 - 0.5*R - 0.5*E;
    r4 = -0.25*a3 - 0.5*R + 0.5*E;
    nr34 = 2;
  }
  else {
    r3 = r4 = -0.25*a3 - 0.5*R;
    nr34 = 0;
  }

  int i=0;
  if (nr12 != 0) {
    roots[i++] = r1;
    roots[i++] = r2;
  }
  if (nr34 != 0) {
    roots[i++] = r3;
    roots[i++] = r4;
  }

  return nr12 + nr34;
}
Beispiel #2
0
int quartic_equation_solve_exact(double *r1, double *r2, double *r3, double *r4,
				 int *nr12, int *nr34,double d0,double d1,double d2, double d3, double d4)
{
  double a3 = d3/d4;
  double a2 = d2/d4;
  double a1 = d1/d4;
  double a0 = d0/d4;

  double au2 = -a2;
  double au1 = (a1*a3 - 4.0*a0) ;
  double au0 = 4.0*a0*a2 - a1*a1 - a0*a3*a3;

  double x1, x2, x3;
  int nr = solve_cubic_equation(1.0, au2, au1, au0, &x1, &x2, &x3);

  double u1;
  if (nr==1) u1 = x1;
  else u1 = (x1>x3) ? x1 : x3;

  double R2 = 0.25*a3*a3 + u1 - a2;
  double R = (R2>0.0) ? sqrt(R2) : 0.0;

  double D2, E2;
  if (R != 0.0)
    {
      double foo1 = 0.75*a3*a3 - R2 - 2.0*a2;
      double foo2 = 0.25*(4.0*a3*a2 - 8.0*a1 - a3*a3*a3) / R;
      D2 = foo1 + foo2;
      E2 = foo1 - foo2;
    }
  else
    {
      double foo1 = 0.75*a3*a3 - 2.0*a2;
      double foo2 = 2.0 * sqrt(u1*u1 - 4.0*a0);
      D2 = foo1 + foo2;
      E2 = foo1 - foo2;
    }

  if (D2 >= 0.0)
    {
      double D = sqrt(D2);
      *r1 = -0.25*a3 + 0.5*R - 0.5*D;
      *r2 = -0.25*a3 + 0.5*R + 0.5*D;
      *nr12 = 2;
    }
  else
    {
      *r1 = *r2 = -0.25*a3 + 0.5*R;
      *nr12 = 0;
    }

  if (E2 >= 0.0)
    {
      double E = sqrt(E2);
      *r3 = -0.25*a3 - 0.5*R - 0.5*E;
      *r4 = -0.25*a3 - 0.5*R + 0.5*E;
      *nr34 = 2;
    }
  else
    {
      *r3 = *r4 = -0.25*a3 - 0.5*R;
      *nr34 = 0;
    }
  return *nr12 + *nr34;
}