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