blob: f776c2d8113003de64faef7905010404cf7573c5 [file] [log] [blame]
caryclark@google.com27accef2012-01-25 18:57:23 +00001#include "CubicUtilities.h"
2#include "DataTypes.h"
3#include "QuadraticUtilities.h"
caryclark@google.com639df892012-01-10 21:46:10 +00004
caryclark@google.com27accef2012-01-25 18:57:23 +00005const double PI = 4 * atan(1);
caryclark@google.com639df892012-01-10 21:46:10 +00006
7static bool is_unit_interval(double x) {
8 return x > 0 && x < 1;
9}
10
caryclark@google.com27accef2012-01-25 18:57:23 +000011// from SkGeometry.cpp (and Numeric Solutions, 5.6)
12int cubicRoots(double A, double B, double C, double D, double t[3]) {
13 if (approximately_zero(A)) { // we're just a quadratic
14 return quadraticRoots(B, C, D, t);
caryclark@google.com639df892012-01-10 21:46:10 +000015 }
caryclark@google.com27accef2012-01-25 18:57:23 +000016 double a, b, c;
17 {
18 double invA = 1 / A;
19 a = B * invA;
20 b = C * invA;
21 c = D * invA;
22 }
caryclark@google.com639df892012-01-10 21:46:10 +000023 double a2 = a * a;
24 double Q = (a2 - b * 3) / 9;
25 double R = (2 * a2 * a - 9 * a * b + 27 * c) / 54;
26 double Q3 = Q * Q * Q;
27 double R2MinusQ3 = R * R - Q3;
28 double adiv3 = a / 3;
caryclark@google.com27accef2012-01-25 18:57:23 +000029 double* roots = t;
caryclark@google.com639df892012-01-10 21:46:10 +000030 double r;
31
32 if (R2MinusQ3 < 0) // we have 3 real roots
33 {
34 double theta = acos(R / sqrt(Q3));
35 double neg2RootQ = -2 * sqrt(Q);
36
37 r = neg2RootQ * cos(theta / 3) - adiv3;
38 if (is_unit_interval(r))
39 *roots++ = r;
40
41 r = neg2RootQ * cos((theta + 2 * PI) / 3) - adiv3;
42 if (is_unit_interval(r))
43 *roots++ = r;
44
45 r = neg2RootQ * cos((theta - 2 * PI) / 3) - adiv3;
46 if (is_unit_interval(r))
47 *roots++ = r;
48 }
49 else // we have 1 real root
50 {
51 double A = fabs(R) + sqrt(R2MinusQ3);
52 A = cube_root(A);
53 if (R > 0) {
54 A = -A;
55 }
56 if (A != 0) {
57 A += Q / A;
58 }
59 r = A - adiv3;
60 if (is_unit_interval(r))
61 *roots++ = r;
62 }
caryclark@google.com27accef2012-01-25 18:57:23 +000063 return (int)(roots - t);
caryclark@google.com639df892012-01-10 21:46:10 +000064}