ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
polynomial_test.cc
Go to the documentation of this file.
1 // Copyright (c) 2018, ETH Zurich and UNC Chapel Hill.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are met:
6 //
7 // * Redistributions of source code must retain the above copyright
8 // notice, this list of conditions and the following disclaimer.
9 //
10 // * Redistributions in binary form must reproduce the above copyright
11 // notice, this list of conditions and the following disclaimer in the
12 // documentation and/or other materials provided with the distribution.
13 //
14 // * Neither the name of ETH Zurich and UNC Chapel Hill nor the names of
15 // its contributors may be used to endorse or promote products derived
16 // from this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
22 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 // POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Author: Johannes L. Schoenberger (jsch-at-demuc-dot-de)
31 
32 #define TEST_NAME "base/polynomial"
33 #include "util/testing.h"
34 
35 #include "base/polynomial.h"
36 
37 using namespace colmap;
38 
39 #define CHECK_EQUAL_RESULT(find_func1, coeffs1, find_func2, coeffs2) \
40  { \
41  Eigen::VectorXd real1; \
42  Eigen::VectorXd imag1; \
43  const bool success1 = find_func1(coeffs1, &real1, &imag1); \
44  Eigen::VectorXd real2; \
45  Eigen::VectorXd imag2; \
46  const bool success2 = find_func2(coeffs2, &real2, &imag2); \
47  BOOST_CHECK_EQUAL(success1, success2); \
48  if (success1) { \
49  BOOST_CHECK_EQUAL(real1, real2); \
50  BOOST_CHECK_EQUAL(imag1, imag2); \
51  } \
52  }
53 
54 BOOST_AUTO_TEST_CASE(TestEvaluatePolynomial) {
55  BOOST_CHECK_EQUAL(EvaluatePolynomial(
56  (Eigen::VectorXd(5) << 1, -3, 3, -5, 10).finished(), 1),
57  1 - 3 + 3 - 5 + 10);
58  BOOST_CHECK_CLOSE(
59  EvaluatePolynomial((Eigen::VectorXd(4) << 1, -3, 3, -5).finished(), 2.0),
60  1 * 2 * 2 * 2 - 3 * 2 * 2 + 3 * 2 - 5, 1e-6);
61 }
62 
63 BOOST_AUTO_TEST_CASE(TestFindLinearPolynomialRoots) {
64  Eigen::VectorXd real;
65  Eigen::VectorXd imag;
66  BOOST_CHECK(FindLinearPolynomialRoots(Eigen::Vector2d(3, -2), &real, &imag));
67  BOOST_CHECK_EQUAL(real(0), 2.0 / 3.0);
68  BOOST_CHECK_EQUAL(imag(0), 0);
69  BOOST_CHECK_CLOSE(EvaluatePolynomial(Eigen::Vector2d(3, -2),
70  std::complex<double>(real(0), imag(0)))
71  .real(),
72  0.0, 1e-6);
73  BOOST_CHECK_CLOSE(EvaluatePolynomial(Eigen::Vector2d(3, -2),
74  std::complex<double>(real(0), imag(0)))
75  .imag(),
76  0.0, 1e-6);
77 
78  BOOST_CHECK(!FindLinearPolynomialRoots(Eigen::Vector2d(0, 1), &real, &imag));
79 }
80 
81 BOOST_AUTO_TEST_CASE(TestFindQuadraticPolynomialRootsReal) {
82  Eigen::VectorXd real;
83  Eigen::VectorXd imag;
84  Eigen::Vector3d coeffs(3, -2, -4);
85  BOOST_CHECK(FindQuadraticPolynomialRoots(coeffs, &real, &imag));
86  BOOST_CHECK(real.isApprox(Eigen::Vector2d(-0.868517092, 1.535183758), 1e-6));
87  BOOST_CHECK_EQUAL(imag, Eigen::Vector2d(0, 0));
88  BOOST_CHECK_CLOSE(
89  EvaluatePolynomial(coeffs, std::complex<double>(real(0), imag(0))).real(),
90  0.0, 1e-6);
91  BOOST_CHECK_CLOSE(
92  EvaluatePolynomial(coeffs, std::complex<double>(real(1), imag(1))).imag(),
93  0.0, 1e-6);
94 }
95 
96 BOOST_AUTO_TEST_CASE(TestFindQuadraticPolynomialRootsComplex) {
97  Eigen::VectorXd real;
98  Eigen::VectorXd imag;
99  const Eigen::Vector3d coeffs(0.276025076998578, 0.679702676853675,
100  0.655098003973841);
101  BOOST_CHECK(FindQuadraticPolynomialRoots(coeffs, &real, &imag));
102  BOOST_CHECK(real.isApprox(
103  Eigen::Vector2d(-1.231233560813707, -1.231233560813707), 1e-6));
104  BOOST_CHECK(imag.isApprox(
105  Eigen::Vector2d(0.925954520440279, -0.925954520440279), 1e-6));
106  BOOST_CHECK_CLOSE(
107  EvaluatePolynomial(coeffs, std::complex<double>(real(0), imag(0))).real(),
108  0.0, 1e-6);
109  BOOST_CHECK_CLOSE(
110  EvaluatePolynomial(coeffs, std::complex<double>(real(1), imag(1))).imag(),
111  0.0, 1e-6);
112 }
113 
114 BOOST_AUTO_TEST_CASE(TestFindPolynomialRootsDurandKerner) {
115  Eigen::VectorXd real;
116  Eigen::VectorXd imag;
117  Eigen::VectorXd coeffs(5);
118  coeffs << 10, -5, 3, -3, 1;
119  BOOST_CHECK(FindPolynomialRootsDurandKerner(coeffs, &real, &imag));
120  // Reference values generated with OpenCV/Matlab.
121  Eigen::VectorXd ref_real(4);
122  ref_real << -0.201826, -0.201826, 0.451826, 0.451826;
123  BOOST_CHECK(real.isApprox(ref_real, 1e-6));
124  Eigen::VectorXd ref_imag(4);
125  ref_imag << -0.627696, 0.627696, 0.160867, -0.160867;
126  BOOST_CHECK(imag.isApprox(ref_imag, 1e-6));
127 }
128 
129 BOOST_AUTO_TEST_CASE(TestFindPolynomialRootsDurandKernerLinearQuadratic) {
131  FindLinearPolynomialRoots, Eigen::Vector2d(1, 2));
133  (Eigen::VectorXd(4) << 0, 0, 1, 2).finished(),
134  FindLinearPolynomialRoots, Eigen::Vector2d(1, 2));
135  CHECK_EQUAL_RESULT(FindPolynomialRootsDurandKerner, Eigen::Vector3d(1, 2, 3),
136  FindQuadraticPolynomialRoots, Eigen::Vector3d(1, 2, 3));
138  (Eigen::VectorXd(5) << 0, 0, 1, 2, 3).finished(),
139  FindQuadraticPolynomialRoots, Eigen::Vector3d(1, 2, 3));
140 }
141 
142 BOOST_AUTO_TEST_CASE(TestFindPolynomialRootsCompanionMatrix) {
143  Eigen::VectorXd real;
144  Eigen::VectorXd imag;
145  Eigen::VectorXd coeffs(5);
146  coeffs << 10, -5, 3, -3, 1;
147  BOOST_CHECK(FindPolynomialRootsCompanionMatrix(coeffs, &real, &imag));
148  // Reference values generated with OpenCV/Matlab.
149  Eigen::VectorXd ref_real(4);
150  ref_real << -0.201826, -0.201826, 0.451826, 0.451826;
151  BOOST_CHECK(real.isApprox(ref_real, 1e-6));
152  Eigen::VectorXd ref_imag(4);
153  ref_imag << 0.627696, -0.627696, 0.160867, -0.160867;
154  BOOST_CHECK(imag.isApprox(ref_imag, 1e-6));
155 }
156 
157 BOOST_AUTO_TEST_CASE(TestFindPolynomialRootsCompanionMatrixLinearQuadratic) {
159  FindLinearPolynomialRoots, Eigen::Vector2d(1, 2));
161  (Eigen::VectorXd(4) << 0, 0, 1, 2).finished(),
162  FindLinearPolynomialRoots, Eigen::Vector2d(1, 2));
164  Eigen::Vector3d(1, 2, 3), FindQuadraticPolynomialRoots,
165  Eigen::Vector3d(1, 2, 3));
167  (Eigen::VectorXd(5) << 0, 0, 1, 2, 3).finished(),
168  FindQuadraticPolynomialRoots, Eigen::Vector3d(1, 2, 3));
169 }
170 
171 BOOST_AUTO_TEST_CASE(TestFindPolynomialRootsCompanionMatrixZeroSolution) {
172  Eigen::VectorXd real;
173  Eigen::VectorXd imag;
174  Eigen::VectorXd coeffs(5);
175  coeffs << 10, -5, 3, -3, 0;
176  BOOST_CHECK(FindPolynomialRootsCompanionMatrix(coeffs, &real, &imag));
177  // Reference values generated with Matlab.
178  Eigen::VectorXd ref_real(4);
179  ref_real << 0.692438, -0.0962191, -0.0962191, 0;
180  BOOST_CHECK(real.isApprox(ref_real, 1e-6));
181  Eigen::VectorXd ref_imag(4);
182  ref_imag << 0, 0.651148, -0.651148, 0;
183  BOOST_CHECK(imag.isApprox(ref_imag, 1e-6));
184 }
coeffs(0)
const double * e
bool FindPolynomialRootsCompanionMatrix(const Eigen::VectorXd &coeffs_all, Eigen::VectorXd *real, Eigen::VectorXd *imag)
Definition: polynomial.cc:208
bool FindLinearPolynomialRoots(const Eigen::VectorXd &coeffs, Eigen::VectorXd *real, Eigen::VectorXd *imag)
Definition: polynomial.cc:65
bool FindQuadraticPolynomialRoots(const Eigen::VectorXd &coeffs, Eigen::VectorXd *real, Eigen::VectorXd *imag)
Definition: polynomial.cc:86
bool FindPolynomialRootsDurandKerner(const Eigen::VectorXd &coeffs_all, Eigen::VectorXd *real, Eigen::VectorXd *imag)
Definition: polynomial.cc:143
T EvaluatePolynomial(const Eigen::VectorXd &coeffs, const T &x)
Definition: polynomial.h:68
BOOST_AUTO_TEST_CASE(TestEvaluatePolynomial)
#define CHECK_EQUAL_RESULT(find_func1, coeffs1, find_func2, coeffs2)