1 // Ceres Solver - A fast non-linear least squares minimizer
2 // Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
3 // http://code.google.com/p/ceres-solver/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright notice,
11 // this list of conditions and the following disclaimer in the documentation
12 // and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors may be
14 // used to endorse or promote products derived from this software without
15 // specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 //
29 // Author: keir@google.com (Keir Mierle)
30
31 #include "ceres/jet.h"
32
33 #include <algorithm>
34 #include <cmath>
35
36 #include "glog/logging.h"
37 #include "gtest/gtest.h"
38 #include "ceres/fpclassify.h"
39 #include "ceres/stringprintf.h"
40 #include "ceres/test_util.h"
41
42 #define VL VLOG(1)
43
44 namespace ceres {
45 namespace internal {
46
47 const double kE = 2.71828182845904523536;
48
49 typedef Jet<double, 2> J;
50
51 // Convenient shorthand for making a jet.
MakeJet(double a,double v0,double v1)52 J MakeJet(double a, double v0, double v1) {
53 J z;
54 z.a = a;
55 z.v[0] = v0;
56 z.v[1] = v1;
57 return z;
58 }
59
60 // On a 32-bit optimized build, the mismatch is about 1.4e-14.
61 double const kTolerance = 1e-13;
62
ExpectJetsClose(const J & x,const J & y)63 void ExpectJetsClose(const J &x, const J &y) {
64 ExpectClose(x.a, y.a, kTolerance);
65 ExpectClose(x.v[0], y.v[0], kTolerance);
66 ExpectClose(x.v[1], y.v[1], kTolerance);
67 }
68
TEST(Jet,Jet)69 TEST(Jet, Jet) {
70 // Pick arbitrary values for x and y.
71 J x = MakeJet(2.3, -2.7, 1e-3);
72 J y = MakeJet(1.7, 0.5, 1e+2);
73
74 VL << "x = " << x;
75 VL << "y = " << y;
76
77 { // Check that log(exp(x)) == x.
78 J z = exp(x);
79 J w = log(z);
80 VL << "z = " << z;
81 VL << "w = " << w;
82 ExpectJetsClose(w, x);
83 }
84
85 { // Check that (x * y) / x == y.
86 J z = x * y;
87 J w = z / x;
88 VL << "z = " << z;
89 VL << "w = " << w;
90 ExpectJetsClose(w, y);
91 }
92
93 { // Check that sqrt(x * x) == x.
94 J z = x * x;
95 J w = sqrt(z);
96 VL << "z = " << z;
97 VL << "w = " << w;
98 ExpectJetsClose(w, x);
99 }
100
101 { // Check that sqrt(y) * sqrt(y) == y.
102 J z = sqrt(y);
103 J w = z * z;
104 VL << "z = " << z;
105 VL << "w = " << w;
106 ExpectJetsClose(w, y);
107 }
108
109 { // Check that cos(2*x) = cos(x)^2 - sin(x)^2
110 J z = cos(J(2.0) * x);
111 J w = cos(x)*cos(x) - sin(x)*sin(x);
112 VL << "z = " << z;
113 VL << "w = " << w;
114 ExpectJetsClose(w, z);
115 }
116
117 { // Check that sin(2*x) = 2*cos(x)*sin(x)
118 J z = sin(J(2.0) * x);
119 J w = J(2.0)*cos(x)*sin(x);
120 VL << "z = " << z;
121 VL << "w = " << w;
122 ExpectJetsClose(w, z);
123 }
124
125 { // Check that cos(x)*cos(x) + sin(x)*sin(x) = 1
126 J z = cos(x) * cos(x);
127 J w = sin(x) * sin(x);
128 VL << "z = " << z;
129 VL << "w = " << w;
130 ExpectJetsClose(z + w, J(1.0));
131 }
132
133 { // Check that atan2(r*sin(t), r*cos(t)) = t.
134 J t = MakeJet(0.7, -0.3, +1.5);
135 J r = MakeJet(2.3, 0.13, -2.4);
136 VL << "t = " << t;
137 VL << "r = " << r;
138
139 J u = atan2(r * sin(t), r * cos(t));
140 VL << "u = " << u;
141
142 ExpectJetsClose(u, t);
143 }
144
145 { // Check that pow(x, 1) == x.
146 VL << "x = " << x;
147
148 J u = pow(x, 1.);
149 VL << "u = " << u;
150
151 ExpectJetsClose(x, u);
152 }
153
154 { // Check that pow(x, 1) == x.
155 J y = MakeJet(1, 0.0, 0.0);
156 VL << "x = " << x;
157 VL << "y = " << y;
158
159 J u = pow(x, y);
160 VL << "u = " << u;
161
162 ExpectJetsClose(x, u);
163 }
164
165 { // Check that pow(e, log(x)) == x.
166 J logx = log(x);
167
168 VL << "x = " << x;
169 VL << "y = " << y;
170
171 J u = pow(kE, logx);
172 VL << "u = " << u;
173
174 ExpectJetsClose(x, u);
175 }
176
177 { // Check that pow(e, log(x)) == x.
178 J logx = log(x);
179 J e = MakeJet(kE, 0., 0.);
180 VL << "x = " << x;
181 VL << "log(x) = " << logx;
182
183 J u = pow(e, logx);
184 VL << "u = " << u;
185
186 ExpectJetsClose(x, u);
187 }
188
189 { // Check that pow(e, log(x)) == x.
190 J logx = log(x);
191 J e = MakeJet(kE, 0., 0.);
192 VL << "x = " << x;
193 VL << "logx = " << logx;
194
195 J u = pow(e, logx);
196 VL << "u = " << u;
197
198 ExpectJetsClose(x, u);
199 }
200
201 { // Check that pow(x,y) = exp(y*log(x)).
202 J logx = log(x);
203 J e = MakeJet(kE, 0., 0.);
204 VL << "x = " << x;
205 VL << "logx = " << logx;
206
207 J u = pow(e, y*logx);
208 J v = pow(x, y);
209 VL << "u = " << u;
210 VL << "v = " << v;
211
212 ExpectJetsClose(v, u);
213 }
214
215 { // Check that 1 + x == x + 1.
216 J a = x + 1.0;
217 J b = 1.0 + x;
218
219 ExpectJetsClose(a, b);
220 }
221
222 { // Check that 1 - x == -(x - 1).
223 J a = 1.0 - x;
224 J b = -(x - 1.0);
225
226 ExpectJetsClose(a, b);
227 }
228
229 { // Check that x/s == x*s.
230 J a = x / 5.0;
231 J b = x * 5.0;
232
233 ExpectJetsClose(5.0 * a, b / 5.0);
234 }
235
236 { // Check that x / y == 1 / (y / x).
237 J a = x / y;
238 J b = 1.0 / (y / x);
239 VL << "a = " << a;
240 VL << "b = " << b;
241
242 ExpectJetsClose(a, b);
243 }
244
245 { // Check that abs(-x * x) == sqrt(x * x).
246 ExpectJetsClose(abs(-x), sqrt(x * x));
247 }
248
249 { // Check that cos(acos(x)) == x.
250 J a = MakeJet(0.1, -2.7, 1e-3);
251 ExpectJetsClose(cos(acos(a)), a);
252 ExpectJetsClose(acos(cos(a)), a);
253
254 J b = MakeJet(0.6, 0.5, 1e+2);
255 ExpectJetsClose(cos(acos(b)), b);
256 ExpectJetsClose(acos(cos(b)), b);
257 }
258
259 { // Check that sin(asin(x)) == x.
260 J a = MakeJet(0.1, -2.7, 1e-3);
261 ExpectJetsClose(sin(asin(a)), a);
262 ExpectJetsClose(asin(sin(a)), a);
263
264 J b = MakeJet(0.4, 0.5, 1e+2);
265 ExpectJetsClose(sin(asin(b)), b);
266 ExpectJetsClose(asin(sin(b)), b);
267 }
268 }
269
TEST(Jet,JetsInEigenMatrices)270 TEST(Jet, JetsInEigenMatrices) {
271 J x = MakeJet(2.3, -2.7, 1e-3);
272 J y = MakeJet(1.7, 0.5, 1e+2);
273 J z = MakeJet(5.3, -4.7, 1e-3);
274 J w = MakeJet(9.7, 1.5, 10.1);
275
276 Eigen::Matrix<J, 2, 2> M;
277 Eigen::Matrix<J, 2, 1> v, r1, r2;
278
279 M << x, y, z, w;
280 v << x, z;
281
282 // Check that M * v == (v^T * M^T)^T
283 r1 = M * v;
284 r2 = (v.transpose() * M.transpose()).transpose();
285
286 ExpectJetsClose(r1(0), r2(0));
287 ExpectJetsClose(r1(1), r2(1));
288 }
289
TEST(JetTraitsTest,ClassificationMixed)290 TEST(JetTraitsTest, ClassificationMixed) {
291 Jet<double, 3> a(5.5, 0);
292 a.v[0] = std::numeric_limits<double>::quiet_NaN();
293 a.v[1] = std::numeric_limits<double>::infinity();
294 a.v[2] = -std::numeric_limits<double>::infinity();
295 EXPECT_FALSE(IsFinite(a));
296 EXPECT_FALSE(IsNormal(a));
297 EXPECT_TRUE(IsInfinite(a));
298 EXPECT_TRUE(IsNaN(a));
299 }
300
TEST(JetTraitsTest,ClassificationNaN)301 TEST(JetTraitsTest, ClassificationNaN) {
302 Jet<double, 3> a(5.5, 0);
303 a.v[0] = std::numeric_limits<double>::quiet_NaN();
304 a.v[1] = 0.0;
305 a.v[2] = 0.0;
306 EXPECT_FALSE(IsFinite(a));
307 EXPECT_FALSE(IsNormal(a));
308 EXPECT_FALSE(IsInfinite(a));
309 EXPECT_TRUE(IsNaN(a));
310 }
311
TEST(JetTraitsTest,ClassificationInf)312 TEST(JetTraitsTest, ClassificationInf) {
313 Jet<double, 3> a(5.5, 0);
314 a.v[0] = std::numeric_limits<double>::infinity();
315 a.v[1] = 0.0;
316 a.v[2] = 0.0;
317 EXPECT_FALSE(IsFinite(a));
318 EXPECT_FALSE(IsNormal(a));
319 EXPECT_TRUE(IsInfinite(a));
320 EXPECT_FALSE(IsNaN(a));
321 }
322
TEST(JetTraitsTest,ClassificationFinite)323 TEST(JetTraitsTest, ClassificationFinite) {
324 Jet<double, 3> a(5.5, 0);
325 a.v[0] = 100.0;
326 a.v[1] = 1.0;
327 a.v[2] = 3.14159;
328 EXPECT_TRUE(IsFinite(a));
329 EXPECT_TRUE(IsNormal(a));
330 EXPECT_FALSE(IsInfinite(a));
331 EXPECT_FALSE(IsNaN(a));
332 }
333
334 } // namespace internal
335 } // namespace ceres
336