Example #1
0
DLLEXPORT int solveCubic(double c3, double c2, double c1, double c0, 
                         double & s0, double & s1, double & s2)
{
    int i, num;
    double  sub,
        A, B, C,
        sq_A, p, q,
        cb_p, D;

    if (isZero(c3))
        return solveQuadric(c2, c1, c0, s0, s1);

    // normalize the equation:x ^ 3 + Ax ^ 2 + Bx  + C = 0
    A = c2 / c3;
    B = c1 / c3;
    C = c0 / c3;

    // substitute x = y - A / 3 to eliminate the quadric term: x^3 + px + q = 0

    sq_A = A * A;
    p = 1.0/3.0 * (-1.0/3.0 * sq_A + B);
    q = 1.0/2.0 * (2.0/27.0 * A *sq_A - 1.0/3.0 * A * B + C);

    // use Cardano's formula

    cb_p = p * p * p;
    D = q * q + cb_p;

    if (isZero(D))
    {
        if (isZero(q))
        {
            // one triple solution
            s0 = 0.0;
            num = 1;
        }
        else
        {
            // one single and one double solution
            double u = cbrt(-q);
            s0 = 2.0 * u;
            s1 = - u;
            num = 2;
        }
    }
    else
        if (D < 0.0)
        {
            // casus irreductibilis: three real solutions
            double phi = 1.0/3.0 * acos(-q / sqrt(-cb_p));
            double t = 2.0 * sqrt(-p);
            s0 = t * cos(phi);
            s1 = -t * cos(phi + M_PI / 3.0);
            s2 = -t * cos(phi - M_PI / 3.0);
            num = 3;
        }
        else
        {
            // one real solution
            double sqrt_D = sqrt(D);
            double u = cbrt(sqrt_D + fabs(q));
            if (q > 0.0)
                s0 = - u + p / u ;
            else
                s0 = u - p / u;
            num = 1;
        }

        // resubstitute
        sub = 1.0 / 3.0 * A;
        s0 -= sub;
        s1 -= sub;
        s2 -= sub;
        return num;
}
Example #2
0
void Photon::choosePointInRect(Float& x, Float& y, const int rectNum, const Float randX, const Float randY)
{

    Rect& rect = m_chunk->m_rects[rectNum];


    Float b1 = m_knotValues[rect.tl];
    Float b2 = m_knotValues[rect.tr] - b1;
    Float b3 = m_knotValues[rect.bl] - b1;
    Float b4 = b1 - m_knotValues[rect.tr] - m_knotValues[rect.bl] + m_knotValues[rect.br];

    int roots;

    {
        Float x1, x2;
        roots = solveQuadric(b2 + 0.5*b4, 0.5*(b1 + 0.5*b3), -randX*(b2+0.5*b4+0.5*b1+0.25*b3), x1, x2);

        if (roots == 1)
            x = x1;
        else if (roots == 2) {

            if (x1 >= 0. && x1 < 1.) {

                x = x1;
            }
            else if (x2 >= 0. && x2 < 1.) {

                x = x2;
            }
            else {

                x = 0.5;
                fprintf(stderr, "x out of range, %f\t%f\n", x1, x2);
            }
        }
    }

    {
        Float y1, y2;
        roots = solveQuadric(0.5*(b3 + b4*x), b1 + b2*x, -randY*(b1+b2*x + 0.5*(b3+b4*x)), y1, y2);

        if (roots == 1)
            y = y1;
        else if (roots == 2) {

            if (y1 >= 0. && y1 < 1.) {

                y = y1;
            }
            else if (y2 >= 0. && y2 < 1.) {

                y = y2;
            }
            else {

                y = 0.5;
                fprintf(stderr, "y out of range, %f\t%f\n", y1, y2);
            }
        }
    }

    x *= rect.width;
    y *= rect.height;

    x += m_chunk->m_knots[rect.tl].x;
    y += m_chunk->m_knots[rect.tl].y;

}
int PolynomialSolver::solveQuartic(float c[5], float s[4])
{
  float	coeffs[4],
        z, u, v, sub,
        A, B, C, D,
        sq_A, p, q, r;
  int i, num;

  // normalize the equation:x ^ 4 + Ax ^ 3 + Bx ^ 2 + Cx + D = 0
  A = c[3] / c[4];
  B = c[2] / c[4];
  C = c[1] / c[4];
  D = c[0] / c[4];

  // subsitute x = y - A / 4 to eliminate the cubic term: x^4 + px^2 + qx + r = 0
  sq_A = A * A;
  p = -3.0f / 8.0f * sq_A + B;
  q = 1.0f / 8.0f * sq_A * A - 1.0f / 2.0f * A * B + C;
  r = -3.0f / 256.0f * sq_A * sq_A + 1.0f / 16.0f * sq_A * B - 1.0f / 4.0f * A * C + D;

  if(isZero(r))
  {
    // no absolute term:y(y ^ 3 + py + q) = 0
    coeffs[0] = q;
    coeffs[1] = p;
    coeffs[2] = 0.0;
    coeffs[3] = 1.0;

    num = solveCubic(coeffs, s);
    s[num++] = 0;
  }
  else
  {
    // solve the resolvent cubic...
    coeffs[0] = 1.0f / 2.0f * r * p - 1.0f / 8.0f * q * q;
    coeffs[1] = -r;
    coeffs[2] = -1.0f / 2.0f * p;
    coeffs[3] = 1.0f;
    (void) solveCubic(coeffs, s);

    // ...and take the one real solution...
    z = s[0];

    // ...to build two quadratic equations
    u = z * z - r;
    v = 2.0f * z - p;

    if(isZero(u))
      u = 0.0;
    else if(u > 0.0f)
      u = std::sqrt(u);
    else
      return 0;

    if(isZero(v))
      v = 0;
    else if(v > 0.0f)
      v = std::sqrt(v);
    else
      return 0;

    coeffs[0] = z - u;
    coeffs[1] = q < 0 ? -v : v;
    coeffs[2] = 1.0f;

    num = solveQuadric(coeffs, s);

    coeffs[0] = z + u;
    coeffs[1] = q < 0 ? v : -v;
    coeffs[2] = 1.0f;

    num += solveQuadric(coeffs, s + num);
  }

  // resubstitute
  sub = 1.0f / 4 * A;
  for(i = 0; i < num; i++)
    s[i] -= sub;

return num;
}
Example #4
0
int PolySolver::solveCubic(FCL_REAL c[4], FCL_REAL s[3])
{
  int i, num;
  FCL_REAL sub, A, B, C, sq_A, p, q, cb_p, D;
  const FCL_REAL ONE_OVER_THREE = 1 / 3.0;
  const FCL_REAL PI = 3.14159265358979323846;

  // make sure we have a d2 equation
  if(isZero(c[3]))
    return solveQuadric(c, s);

  // normalize the equation:x ^ 3 + Ax ^ 2 + Bx  + C = 0
  A = c[2] / c[3];
  B = c[1] / c[3];
  C = c[0] / c[3];

  // substitute x = y - A / 3 to eliminate the quadratic term: x^3 + px + q = 0
  sq_A = A * A;
  p = (-ONE_OVER_THREE * sq_A + B) * ONE_OVER_THREE;
  q = 0.5 * (2.0 / 27.0 * A * sq_A - ONE_OVER_THREE * A * B + C);

  // use Cardano's formula
  cb_p = p * p * p;
  D = q * q + cb_p;

  if(isZero(D))
  {
    if(isZero(q))
    {
      // one triple solution
      s[0] = 0.0;
      num = 1;
    }
    else
    {
      // one single and one FCL_REAL solution
      FCL_REAL u = cbrt(-q);
      s[0] = 2.0 * u;
      s[1] = -u;
      num = 2;
    }
  }
  else
  {
    if(D < 0.0)
    {
      // three real solutions
      FCL_REAL phi = ONE_OVER_THREE * acos(-q / sqrt(-cb_p));
      FCL_REAL t = 2.0 * sqrt(-p);
      s[0] = t * cos(phi);
      s[1] = -t * cos(phi + PI / 3.0);
      s[2] = -t * cos(phi - PI / 3.0);
      num = 3;
    }
    else
    {
      // one real solution
      FCL_REAL sqrt_D = sqrt(D);
      FCL_REAL u = cbrt(sqrt_D + fabs(q));
      if(q > 0.0)
        s[0] = - u + p / u ;
      else
        s[0] = u - p / u;
      num = 1;
    }
  }

  // re-substitute
  sub = ONE_OVER_THREE * A;
  for(i = 0; i < num; i++)
    s[i] -= sub;
  return num;
}
int solveQuartic(float c[5], float s[4])
{
	float  coeffs[4];
	float  z, u, v, sub;
	float  A, B, C, D;
	float  sq_A, p, q, r;
	int     i, num;

	/* normal form: x^4 + Ax^3 + Bx^2 + Cx + D = 0 */

	A = c[ 3 ] / c[ 4 ];
	B = c[ 2 ] / c[ 4 ];
	C = c[ 1 ] / c[ 4 ];
	D = c[ 0 ] / c[ 4 ];

	/*  substitute x = y - A/4 to eliminate cubic term:
	x^4 + px^2 + qx + r = 0 */

	sq_A = A * A;
	p = - 3.0/8 * sq_A + B;
	q = 1.0/8 * sq_A * A - 1.0/2 * A * B + C;
	r = - 3.0/256*sq_A*sq_A + 1.0/16*sq_A*B - 1.0/4*A*C + D;

	if (IS_ZERO(r)) 
	{
		/* no absolute term: y(y^3 + py + q) = 0 */

		coeffs[ 0 ] = q;
		coeffs[ 1 ] = p;
		coeffs[ 2 ] = 0;
		coeffs[ 3 ] = 1;

		num = solveCubic(coeffs, s);

		s[ num++ ] = 0;
	}
	else {
		/* solve the resolvent cubic ... */

		coeffs[ 0 ] = 1.0/2 * r * p - 1.0/8 * q * q;
		coeffs[ 1 ] = - r;
		coeffs[ 2 ] = - 1.0/2 * p;
		coeffs[ 3 ] = 1;

		(void) solveCubic(coeffs, s);

		/* ... and take the one real solution ... */

		z = s[ 0 ];

		/* ... to build two quadric equations */

		u = z * z - r;
		v = 2 * z - p;

		if (IS_ZERO(u))
			u = 0;
		else if (u > 0)
			u = sqrt(u);
		else
			return 0;

		if (IS_ZERO(v))
			v = 0;
		else if (v > 0)
			v = sqrt(v);
		else
			return 0;

		coeffs[ 0 ] = z - u;
		coeffs[ 1 ] = q < 0 ? -v : v;
		coeffs[ 2 ] = 1;

		num = solveQuadric(coeffs, s);

		coeffs[ 0 ]= z + u;
		coeffs[ 1 ] = q < 0 ? v : -v;
		coeffs[ 2 ] = 1;

		num += solveQuadric(coeffs, s + num);
	}

	/* resubstitute */

	sub = 1.0/4 * A;

	for (i = 0; i < num; ++i)
		s[ i ] -= sub;

	return num;
}