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/include/ceres/fpclassify.h b/include/ceres/fpclassify.h
new file mode 100644
index 0000000..59424bf
--- /dev/null
+++ b/include/ceres/fpclassify.h
@@ -0,0 +1,49 @@
+// Ceres Solver - A fast non-linear least squares minimizer
+// Copyright 2012 Google Inc. All rights reserved.
+// http://code.google.com/p/ceres-solver/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+//   this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+//   this list of conditions and the following disclaimer in the documentation
+//   and/or other materials provided with the distribution.
+// * Neither the name of Google Inc. nor the names of its contributors may be
+//   used to endorse or promote products derived from this software without
+//   specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+// Author: keir@google.com (Keir Mierle)
+//
+// Portable floating point classification. The names are picked such that they
+// do not collide with macros. For example, "isnan" in C99 is a macro and hence
+// does not respect namespaces.
+//
+// TODO(keir): Finish porting!
+
+#ifndef CERES_PUBLIC_FPCLASSIFY_H_
+#define CERES_PUBLIC_FPCLASSIFY_H_
+
+namespace ceres {
+
+inline bool IsFinite  (double x) { return std::isfinite(x); }
+inline bool IsInfinite(double x) { return std::isinf(x);    }
+inline bool IsNaN     (double x) { return std::isnan(x);    }
+inline bool IsNormal  (double x) { return std::isnormal(x); }
+
+}  // namespace ceres
+
+#endif  // CERES_PUBLIC_FPCLASSIFY_H_
diff --git a/include/ceres/jet.h b/include/ceres/jet.h
index 50b5555..f9997bd 100644
--- a/include/ceres/jet.h
+++ b/include/ceres/jet.h
@@ -162,6 +162,7 @@
 #include <string>
 
 #include "Eigen/Core"
+#include "ceres/fpclassify.h"
 
 namespace ceres {
 
@@ -401,10 +402,6 @@
 inline double acos    (double x) { return std::acos(x);     }
 inline double sin     (double x) { return std::sin(x);      }
 inline double asin    (double x) { return std::asin(x);     }
-inline bool   isfinite(double x) { return std::isfinite(x); }
-inline bool   isinf   (double x) { return std::isinf(x);    }
-inline bool   isnan   (double x) { return std::isnan(x);    }
-inline bool   isnormal(double x) { return std::isnormal(x); }
 inline double pow  (double x, double y) { return std::pow(x, y);   }
 inline double atan2(double y, double x) { return std::atan2(y, x); }
 
@@ -482,22 +479,23 @@
 }
 
 // Jet Classification. It is not clear what the appropriate semantics are for
-// these classifications. This picks that isfinite and isnormal are "all"
-// operations, i.e. all elements of the jet must be finite for the jet itself to
-// be finite (or normal). For isnan and isinf, the answer is less clear. This
-// takes a "any" approach for isnan and isinf such that if any part of a jet is
-// nan or inf, then the entire jet is nan or inf. This leads to strange
-// situations like a jet can be both isinf and isnan, but in practice the "any"
-// semantics are the most useful for e.g. checking that derivatives are sane.
+// these classifications. This picks that IsFinite and isnormal are "all"
+// operations, i.e. all elements of the jet must be finite for the jet itself
+// to be finite (or normal). For IsNaN and IsInfinite, the answer is less
+// clear. This takes a "any" approach for IsNaN and IsInfinite such that if any
+// part of a jet is nan or inf, then the entire jet is nan or inf. This leads
+// to strange situations like a jet can be both IsInfinite and IsNaN, but in
+// practice the "any" semantics are the most useful for e.g. checking that
+// derivatives are sane.
 
 // The jet is finite if all parts of the jet are finite.
 template <typename T, int N> inline
-bool isfinite(const Jet<T, N>& f) {
-  if (!isfinite(f.a)) {
+bool IsFinite(const Jet<T, N>& f) {
+  if (!IsFinite(f.a)) {
     return false;
   }
   for (int i = 0; i < N; ++i) {
-    if (!isfinite(f.v[i])) {
+    if (!IsFinite(f.v[i])) {
       return false;
     }
   }
@@ -506,12 +504,12 @@
 
 // The jet is infinite if any part of the jet is infinite.
 template <typename T, int N> inline
-bool isinf(const Jet<T, N>& f) {
-  if (isinf(f.a)) {
+bool IsInfinite(const Jet<T, N>& f) {
+  if (IsInfinite(f.a)) {
     return true;
   }
   for (int i = 0; i < N; i++) {
-    if (isinf(f.v[i])) {
+    if (IsFinite(f.v[i])) {
       return true;
     }
   }
@@ -520,12 +518,12 @@
 
 // The jet is NaN if any part of the jet is NaN.
 template <typename T, int N> inline
-bool isnan(const Jet<T, N>& f) {
-  if (isnan(f.a)) {
+bool IsNaN(const Jet<T, N>& f) {
+  if (IsNaN(f.a)) {
     return true;
   }
   for (int i = 0; i < N; ++i) {
-    if (isnan(f.v[i])) {
+    if (IsNaN(f.v[i])) {
       return true;
     }
   }
@@ -534,12 +532,12 @@
 
 // The jet is normal if all parts of the jet are normal.
 template <typename T, int N> inline
-bool isnormal(const Jet<T, N>& f) {
-  if (!isnormal(f.a)) {
+bool IsNormal(const Jet<T, N>& f) {
+  if (!IsNormal(f.a)) {
     return false;
   }
   for (int i = 0; i < N; ++i) {
-    if (!isnormal(f.v[i])) {
+    if (!IsNormal(f.v[i])) {
       return false;
     }
   }