Home | History | Annotate | Download | only in ceres
      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 (at) 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.
     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 
     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 
     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 tan(x) = sin(x) / cos(x).
    146     J z = tan(x);
    147     J w = sin(x) / cos(x);
    148     VL << "z = " << z;
    149     VL << "w = " << w;
    150     ExpectJetsClose(z, w);
    151   }
    152 
    153   { // Check that tan(atan(x)) = x.
    154     J z = tan(atan(x));
    155     J w = x;
    156     VL << "z = " << z;
    157     VL << "w = " << w;
    158     ExpectJetsClose(z, w);
    159   }
    160 
    161   { // Check that cosh(x)*cosh(x) - sinh(x)*sinh(x) = 1
    162     J z = cosh(x) * cosh(x);
    163     J w = sinh(x) * sinh(x);
    164     VL << "z = " << z;
    165     VL << "w = " << w;
    166     ExpectJetsClose(z - w, J(1.0));
    167   }
    168 
    169   { // Check that tanh(x + y) = (tanh(x) + tanh(y)) / (1 + tanh(x) tanh(y))
    170     J z = tanh(x + y);
    171     J w = (tanh(x) + tanh(y)) / (J(1.0) + tanh(x) * tanh(y));
    172     VL << "z = " << z;
    173     VL << "w = " << w;
    174     ExpectJetsClose(z, w);
    175   }
    176 
    177   { // Check that pow(x, 1) == x.
    178     VL << "x = " << x;
    179 
    180     J u = pow(x, 1.);
    181     VL << "u = " << u;
    182 
    183     ExpectJetsClose(x, u);
    184   }
    185 
    186   { // Check that pow(x, 1) == x.
    187     J y = MakeJet(1, 0.0, 0.0);
    188     VL << "x = " << x;
    189     VL << "y = " << y;
    190 
    191     J u = pow(x, y);
    192     VL << "u = " << u;
    193 
    194     ExpectJetsClose(x, u);
    195   }
    196 
    197   { // Check that pow(e, log(x)) == x.
    198     J logx = log(x);
    199 
    200     VL << "x = " << x;
    201     VL << "y = " << y;
    202 
    203     J u = pow(kE, logx);
    204     VL << "u = " << u;
    205 
    206     ExpectJetsClose(x, u);
    207   }
    208 
    209   { // Check that pow(e, log(x)) == x.
    210     J logx = log(x);
    211     J e = MakeJet(kE, 0., 0.);
    212     VL << "x = " << x;
    213     VL << "log(x) = " << logx;
    214 
    215     J u = pow(e, logx);
    216     VL << "u = " << u;
    217 
    218     ExpectJetsClose(x, u);
    219   }
    220 
    221   { // Check that pow(e, log(x)) == x.
    222     J logx = log(x);
    223     J e = MakeJet(kE, 0., 0.);
    224     VL << "x = " << x;
    225     VL << "logx = " << logx;
    226 
    227     J u = pow(e, logx);
    228     VL << "u = " << u;
    229 
    230     ExpectJetsClose(x, u);
    231   }
    232 
    233   { // Check that pow(x,y) = exp(y*log(x)).
    234     J logx = log(x);
    235     J e = MakeJet(kE, 0., 0.);
    236     VL << "x = " << x;
    237     VL << "logx = " << logx;
    238 
    239     J u = pow(e, y*logx);
    240     J v = pow(x, y);
    241     VL << "u = " << u;
    242     VL << "v = " << v;
    243 
    244     ExpectJetsClose(v, u);
    245   }
    246 
    247   { // Check that 1 + x == x + 1.
    248     J a = x + 1.0;
    249     J b = 1.0 + x;
    250 
    251     ExpectJetsClose(a, b);
    252   }
    253 
    254   { // Check that 1 - x == -(x - 1).
    255     J a = 1.0 - x;
    256     J b = -(x - 1.0);
    257 
    258     ExpectJetsClose(a, b);
    259   }
    260 
    261   { // Check that x/s == x*s.
    262     J a = x / 5.0;
    263     J b = x * 5.0;
    264 
    265     ExpectJetsClose(5.0 * a, b / 5.0);
    266   }
    267 
    268   { // Check that x / y == 1 / (y / x).
    269     J a = x / y;
    270     J b = 1.0 / (y / x);
    271     VL << "a = " << a;
    272     VL << "b = " << b;
    273 
    274     ExpectJetsClose(a, b);
    275   }
    276 
    277   { // Check that abs(-x * x) == sqrt(x * x).
    278     ExpectJetsClose(abs(-x), sqrt(x * x));
    279   }
    280 
    281   { // Check that cos(acos(x)) == x.
    282     J a = MakeJet(0.1, -2.7, 1e-3);
    283     ExpectJetsClose(cos(acos(a)), a);
    284     ExpectJetsClose(acos(cos(a)), a);
    285 
    286     J b = MakeJet(0.6,  0.5, 1e+2);
    287     ExpectJetsClose(cos(acos(b)), b);
    288     ExpectJetsClose(acos(cos(b)), b);
    289   }
    290 
    291   { // Check that sin(asin(x)) == x.
    292     J a = MakeJet(0.1, -2.7, 1e-3);
    293     ExpectJetsClose(sin(asin(a)), a);
    294     ExpectJetsClose(asin(sin(a)), a);
    295 
    296     J b = MakeJet(0.4,  0.5, 1e+2);
    297     ExpectJetsClose(sin(asin(b)), b);
    298     ExpectJetsClose(asin(sin(b)), b);
    299   }
    300 }
    301 
    302 TEST(Jet, JetsInEigenMatrices) {
    303   J x = MakeJet(2.3, -2.7, 1e-3);
    304   J y = MakeJet(1.7,  0.5, 1e+2);
    305   J z = MakeJet(5.3, -4.7, 1e-3);
    306   J w = MakeJet(9.7,  1.5, 10.1);
    307 
    308   Eigen::Matrix<J, 2, 2> M;
    309   Eigen::Matrix<J, 2, 1> v, r1, r2;
    310 
    311   M << x, y, z, w;
    312   v << x, z;
    313 
    314   // Check that M * v == (v^T * M^T)^T
    315   r1 = M * v;
    316   r2 = (v.transpose() * M.transpose()).transpose();
    317 
    318   ExpectJetsClose(r1(0), r2(0));
    319   ExpectJetsClose(r1(1), r2(1));
    320 }
    321 
    322 TEST(JetTraitsTest, ClassificationMixed) {
    323   Jet<double, 3> a(5.5, 0);
    324   a.v[0] = std::numeric_limits<double>::quiet_NaN();
    325   a.v[1] = std::numeric_limits<double>::infinity();
    326   a.v[2] = -std::numeric_limits<double>::infinity();
    327   EXPECT_FALSE(IsFinite(a));
    328   EXPECT_FALSE(IsNormal(a));
    329   EXPECT_TRUE(IsInfinite(a));
    330   EXPECT_TRUE(IsNaN(a));
    331 }
    332 
    333 TEST(JetTraitsTest, ClassificationNaN) {
    334   Jet<double, 3> a(5.5, 0);
    335   a.v[0] = std::numeric_limits<double>::quiet_NaN();
    336   a.v[1] = 0.0;
    337   a.v[2] = 0.0;
    338   EXPECT_FALSE(IsFinite(a));
    339   EXPECT_FALSE(IsNormal(a));
    340   EXPECT_FALSE(IsInfinite(a));
    341   EXPECT_TRUE(IsNaN(a));
    342 }
    343 
    344 TEST(JetTraitsTest, ClassificationInf) {
    345   Jet<double, 3> a(5.5, 0);
    346   a.v[0] = std::numeric_limits<double>::infinity();
    347   a.v[1] = 0.0;
    348   a.v[2] = 0.0;
    349   EXPECT_FALSE(IsFinite(a));
    350   EXPECT_FALSE(IsNormal(a));
    351   EXPECT_TRUE(IsInfinite(a));
    352   EXPECT_FALSE(IsNaN(a));
    353 }
    354 
    355 TEST(JetTraitsTest, ClassificationFinite) {
    356   Jet<double, 3> a(5.5, 0);
    357   a.v[0] = 100.0;
    358   a.v[1] = 1.0;
    359   a.v[2] = 3.14159;
    360   EXPECT_TRUE(IsFinite(a));
    361   EXPECT_TRUE(IsNormal(a));
    362   EXPECT_FALSE(IsInfinite(a));
    363   EXPECT_FALSE(IsNaN(a));
    364 }
    365 
    366 }  // namespace internal
    367 }  // namespace ceres
    368