Add a portable floating point classification API

Ceres has traditionally battled with portability issues
when trying to classify floating point values as one
type or another. For example, in C99 'isnan' is a
macro. Since it is a macro, it is impossible to
override the name in other namespaces.

Instead of trying to use preprocessor hacks to work
around the issue, define our own set of camel-case
names for use internally and by Ceres clients. For
example do this:

  template<typename T>
  void MyFunction(T x, T y) {
    if (ceres::IsNaN(x)) {
      ...
    }
  }

instead of using "isnan" or "std::isnan". Note that
while GCC and Apple GCC both import 'isnan' into
the std namespace, it is not standard until C++11
which Ceres will not require for some years.

Change-Id: Ibcc96a8bb4ba63aa67cbbc58658b2e5671cd5824
diff --git a/internal/ceres/array_utils.cc b/internal/ceres/array_utils.cc
index aab0c21..673baa4 100644
--- a/internal/ceres/array_utils.cc
+++ b/internal/ceres/array_utils.cc
@@ -32,6 +32,7 @@
 
 #include <cmath>
 #include <cstddef>
+#include "ceres/fpclassify.h"
 
 namespace ceres {
 namespace internal {
@@ -46,7 +47,7 @@
 bool IsArrayValid(const int size, const double* x) {
   if (x != NULL) {
     for (int i = 0; i < size; ++i) {
-      if (!isfinite(x[i]) || (x[i] == kImpossibleValue))  {
+      if (!IsFinite(x[i]) || (x[i] == kImpossibleValue))  {
         return false;
       }
     }
diff --git a/internal/ceres/conjugate_gradients_solver.cc b/internal/ceres/conjugate_gradients_solver.cc
index 09a0279..7501bb2 100644
--- a/internal/ceres/conjugate_gradients_solver.cc
+++ b/internal/ceres/conjugate_gradients_solver.cc
@@ -42,6 +42,7 @@
 #include <cmath>
 #include <cstddef>
 #include <glog/logging.h>
+#include "ceres/fpclassify.h"
 #include "ceres/linear_operator.h"
 #include "ceres/internal/eigen.h"
 #include "ceres/types.h"
@@ -51,7 +52,7 @@
 namespace {
 
 bool IsZeroOrInfinity(double x) {
-  return ((x == 0.0) || (isinf(x)));
+  return ((x == 0.0) || (IsInfinite(x)));
 }
 
 // Constant used in the MATLAB implementation ~ 2 * eps.
@@ -150,14 +151,14 @@
     A->RightMultiply(p.data(), q.data());
     double pq = p.dot(q);
 
-    if ((pq <= 0) || isinf(pq))  {
+    if ((pq <= 0) || IsInfinite(pq))  {
       LOG(ERROR) << "Numerical failure. pq = " << pq;
       summary.termination_type = FAILURE;
       break;
     }
 
     double alpha = rho / pq;
-    if (isinf(alpha)) {
+    if (IsInfinite(alpha)) {
       LOG(ERROR) << "Numerical failure. alpha " << alpha;
       summary.termination_type = FAILURE;
       break;
diff --git a/internal/ceres/jet_test.cc b/internal/ceres/jet_test.cc
index 2e47b63..f12b8b9 100644
--- a/internal/ceres/jet_test.cc
+++ b/internal/ceres/jet_test.cc
@@ -35,6 +35,7 @@
 
 #include <glog/logging.h>
 #include "gtest/gtest.h"
+#include "ceres/fpclassify.h"
 #include "ceres/stringprintf.h"
 #include "ceres/test_util.h"
 
@@ -289,10 +290,10 @@
   a.v[0] = std::numeric_limits<double>::quiet_NaN();
   a.v[1] = std::numeric_limits<double>::infinity();
   a.v[2] = -std::numeric_limits<double>::infinity();
-  EXPECT_FALSE(isfinite(a));
-  EXPECT_FALSE(isnormal(a));
-  EXPECT_TRUE(isinf(a));
-  EXPECT_TRUE(isnan(a));
+  EXPECT_FALSE(IsFinite(a));
+  EXPECT_FALSE(IsNormal(a));
+  EXPECT_TRUE(IsInfinite(a));
+  EXPECT_TRUE(IsNaN(a));
 }
 
 TEST(JetTraitsTest, ClassificationNaN) {
@@ -300,10 +301,10 @@
   a.v[0] = std::numeric_limits<double>::quiet_NaN();
   a.v[1] = 0.0;
   a.v[2] = 0.0;
-  EXPECT_FALSE(isfinite(a));
-  EXPECT_FALSE(isnormal(a));
-  EXPECT_FALSE(isinf(a));
-  EXPECT_TRUE(isnan(a));
+  EXPECT_FALSE(IsFinite(a));
+  EXPECT_FALSE(IsNormal(a));
+  EXPECT_FALSE(IsInfinite(a));
+  EXPECT_TRUE(IsNaN(a));
 }
 
 TEST(JetTraitsTest, ClassificationInf) {
@@ -311,10 +312,10 @@
   a.v[0] = std::numeric_limits<double>::infinity();
   a.v[1] = 0.0;
   a.v[2] = 0.0;
-  EXPECT_FALSE(isfinite(a));
-  EXPECT_FALSE(isnormal(a));
-  EXPECT_TRUE(isinf(a));
-  EXPECT_FALSE(isnan(a));
+  EXPECT_FALSE(IsFinite(a));
+  EXPECT_FALSE(IsNormal(a));
+  EXPECT_TRUE(IsInfinite(a));
+  EXPECT_FALSE(IsNaN(a));
 }
 
 TEST(JetTraitsTest, ClassificationFinite) {
@@ -322,10 +323,10 @@
   a.v[0] = 100.0;
   a.v[1] = 1.0;
   a.v[2] = 3.14159;
-  EXPECT_TRUE(isfinite(a));
-  EXPECT_TRUE(isnormal(a));
-  EXPECT_FALSE(isinf(a));
-  EXPECT_FALSE(isnan(a));
+  EXPECT_TRUE(IsFinite(a));
+  EXPECT_TRUE(IsNormal(a));
+  EXPECT_FALSE(IsInfinite(a));
+  EXPECT_FALSE(IsNaN(a));
 }
 
 }  // namespace internal
diff --git a/internal/ceres/local_parameterization_test.cc b/internal/ceres/local_parameterization_test.cc
index 8315e8e..aa49250 100644
--- a/internal/ceres/local_parameterization_test.cc
+++ b/internal/ceres/local_parameterization_test.cc
@@ -30,6 +30,7 @@
 
 #include <cmath>
 #include "gtest/gtest.h"
+#include "ceres/fpclassify.h"
 #include "ceres/internal/autodiff.h"
 #include "ceres/internal/eigen.h"
 #include "ceres/local_parameterization.h"
@@ -183,7 +184,7 @@
   double jacobian[12];
   param.ComputeJacobian(x, jacobian);
   for (int i = 0; i < 12; ++i) {
-    EXPECT_TRUE(isfinite(jacobian[i]));
+    EXPECT_TRUE(IsFinite(jacobian[i]));
     EXPECT_NEAR(jacobian[i], jacobian_ref[i], kTolerance)
         << "Jacobian mismatch: i = " << i
         << "\n Expected \n" << ConstMatrixRef(jacobian_ref, 4, 3)
diff --git a/internal/ceres/rotation_test.cc b/internal/ceres/rotation_test.cc
index a8351d5..55a4fbb 100644
--- a/internal/ceres/rotation_test.cc
+++ b/internal/ceres/rotation_test.cc
@@ -591,8 +591,8 @@
 
 
 bool IsClose(double x, double y) {
-  EXPECT_FALSE(isnan(x));
-  EXPECT_FALSE(isnan(y));
+  EXPECT_FALSE(IsNaN(x));
+  EXPECT_FALSE(IsNaN(y));
   double absdiff = fabs(x - y);
   if (x == 0 || y == 0) {
     return absdiff <= kTolerance;