| caryclark@google.com | 235f56a | 2012-09-14 14:19:30 +0000 | [diff] [blame^] | 1 | #include <assert.h> |
| 2 | #include <math.h> |
| 3 | #include "CubicUtilities.h" |
| 4 | #include "Intersection_Tests.h" |
| 5 | |
| 6 | namespace QuarticRootTest { |
| 7 | |
| 8 | #include "QuarticRoot.cpp" |
| 9 | |
| 10 | } |
| 11 | |
| 12 | double mulA[] = {-3, -1, 1, 3}; |
| 13 | size_t mulACount = sizeof(mulA) / sizeof(mulA[0]); |
| 14 | double rootB[] = {-9, -6, -3, -1, 0, 1, 3, 6, 9}; |
| 15 | size_t rootBCount = sizeof(rootB) / sizeof(rootB[0]); |
| 16 | double rootC[] = {-8, -6, -2, -1, 0, 1, 2, 6, 8}; |
| 17 | size_t rootCCount = sizeof(rootC) / sizeof(rootC[0]); |
| 18 | double rootD[] = {-7, -4, -1, 0, 1, 2, 5}; |
| 19 | size_t rootDCount = sizeof(rootD) / sizeof(rootD[0]); |
| 20 | double rootE[] = {-5, -1, 0, 1, 7}; |
| 21 | size_t rootECount = sizeof(rootE) / sizeof(rootE[0]); |
| 22 | |
| 23 | static 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 | |
| 49 | static 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 | |
| 88 | static 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 | |
| 144 | void QuarticRoot_Test() { |
| 145 | quadraticTest(); |
| 146 | cubicTest(); |
| 147 | quarticTest(); |
| 148 | } |