blob: 2fe3e728c1197eff0b0f22c300d143027b9a95a7 [file] [log] [blame]
caryclark@google.com235f56a2012-09-14 14:19:30 +00001#include <assert.h>
2#include <math.h>
3#include "CubicUtilities.h"
4#include "Intersection_Tests.h"
5
6namespace QuarticRootTest {
7
8#include "QuarticRoot.cpp"
9
10}
11
12double mulA[] = {-3, -1, 1, 3};
13size_t mulACount = sizeof(mulA) / sizeof(mulA[0]);
14double rootB[] = {-9, -6, -3, -1, 0, 1, 3, 6, 9};
15size_t rootBCount = sizeof(rootB) / sizeof(rootB[0]);
16double rootC[] = {-8, -6, -2, -1, 0, 1, 2, 6, 8};
17size_t rootCCount = sizeof(rootC) / sizeof(rootC[0]);
18double rootD[] = {-7, -4, -1, 0, 1, 2, 5};
19size_t rootDCount = sizeof(rootD) / sizeof(rootD[0]);
20double rootE[] = {-5, -1, 0, 1, 7};
21size_t rootECount = sizeof(rootE) / sizeof(rootE[0]);
22
23static void quadraticTest() {
24 // (x - a)(x - b) == x^2 - (a + b)x + ab
25 for (size_t aIndex = 0; aIndex < mulACount; ++aIndex) {
26 for (size_t bIndex = 0; bIndex < rootBCount; ++bIndex) {
27 for (size_t cIndex = 0; cIndex < rootCCount; ++cIndex) {
28 const double A = mulA[aIndex];
29 const double B = rootB[bIndex];
30 const double C = rootC[cIndex];
31 const double b = A * (B + C);
32 const double c = A * B * C;
33 double roots[2];
34 const int rootCount = QuarticRootTest::quadraticRootsX(A, b, c, roots);
35 const int expected = 1 + (B != C);
36 assert(rootCount == expected);
37 assert(approximately_equal(roots[0], -B)
38 || approximately_equal(roots[0], -C));
39 if (B != C) {
40 assert(!approximately_equal(roots[0], roots[1]));
41 assert(approximately_equal(roots[1], -B)
42 || approximately_equal(roots[1], -C));
43 }
44 }
45 }
46 }
47}
48
49static void cubicTest() {
50 // (x - a)(x - b)(x - c) == x^3 - (a + b + c)x^2 + (ab + bc + ac)x - abc
51 for (size_t aIndex = 0; aIndex < mulACount; ++aIndex) {
52 for (size_t bIndex = 0; bIndex < rootBCount; ++bIndex) {
53 for (size_t cIndex = 0; cIndex < rootCCount; ++cIndex) {
54 for (size_t dIndex = 0; dIndex < rootDCount; ++dIndex) {
55 const double A = mulA[aIndex];
56 const double B = rootB[bIndex];
57 const double C = rootC[cIndex];
58 const double D = rootD[dIndex];
59 const double b = A * (B + C + D);
60 const double c = A * (B * C + C * D + B * D);
61 const double d = A * B * C * D;
62 double roots[3];
63 const int rootCount = QuarticRootTest::cubicRootsX(A, b, c, d, roots);
64 const int expected = 1 + (B != C) + (B != D && C != D);
65 assert(rootCount == expected);
66 assert(approximately_equal(roots[0], -B)
67 || approximately_equal(roots[0], -C)
68 || approximately_equal(roots[0], -D));
69 if (expected > 1) {
70 assert(!approximately_equal(roots[0], roots[1]));
71 assert(approximately_equal(roots[1], -B)
72 || approximately_equal(roots[1], -C)
73 || approximately_equal(roots[1], -D));
74 if (expected > 2) {
75 assert(!approximately_equal(roots[0], roots[2])
76 && !approximately_equal(roots[1], roots[2]));
77 assert(approximately_equal(roots[2], -B)
78 || approximately_equal(roots[2], -C)
79 || approximately_equal(roots[2], -D));
80 }
81 }
82 }
83 }
84 }
85 }
86}
87
88static void quarticTest() {
89 // (x - a)(x - b)(x - c)(x - d) == x^4 - (a + b + c + d)x^3
90 // + (ab + bc + cd + ac + bd + cd)x^2 - (abc + bcd + abd + acd) * x + abcd
91 for (size_t aIndex = 0; aIndex < mulACount; ++aIndex) {
92 for (size_t bIndex = 0; bIndex < rootBCount; ++bIndex) {
93 for (size_t cIndex = 0; cIndex < rootCCount; ++cIndex) {
94 for (size_t dIndex = 0; dIndex < rootDCount; ++dIndex) {
95 for (size_t eIndex = 0; eIndex < rootECount; ++eIndex) {
96 const double A = mulA[aIndex];
97 const double B = rootB[bIndex];
98 const double C = rootC[cIndex];
99 const double D = rootD[dIndex];
100 const double E = rootE[eIndex];
101 const double b = A * (B + C + D + E);
102 const double c = A * (B * C + C * D + B * D + B * E + C * E + D * E);
103 const double d = A * (B * C * D + B * C * E + B * D * E + C * D * E);
104 const double e = A * B * C * D * E;
105 double roots[4];
106 const int rootCount = QuarticRootTest::quarticRoots(A, b, c, d, e, roots);
107 const int expected = 1 + (B != C) + (B != D && C != D) + (B != E && C != E && D != E);
108 assert(rootCount == expected);
109 assert(approximately_equal(roots[0], -B)
110 || approximately_equal(roots[0], -C)
111 || approximately_equal(roots[0], -D)
112 || approximately_equal(roots[0], -E));
113 if (expected > 1) {
114 assert(!approximately_equal(roots[0], roots[1]));
115 assert(approximately_equal(roots[1], -B)
116 || approximately_equal(roots[1], -C)
117 || approximately_equal(roots[1], -D)
118 || approximately_equal(roots[1], -E));
119 if (expected > 2) {
120 assert(!approximately_equal(roots[0], roots[2])
121 && !approximately_equal(roots[1], roots[2]));
122 assert(approximately_equal(roots[2], -B)
123 || approximately_equal(roots[2], -C)
124 || approximately_equal(roots[2], -D)
125 || approximately_equal(roots[2], -E));
126 if (expected > 3) {
127 assert(!approximately_equal(roots[0], roots[3])
128 && !approximately_equal(roots[1], roots[3])
129 && !approximately_equal(roots[2], roots[3]));
130 assert(approximately_equal(roots[3], -B)
131 || approximately_equal(roots[3], -C)
132 || approximately_equal(roots[3], -D)
133 || approximately_equal(roots[3], -E));
134 }
135 }
136 }
137 }
138 }
139 }
140 }
141 }
142}
143
144void QuarticRoot_Test() {
145 quadraticTest();
146 cubicTest();
147 quarticTest();
148}